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();
2551 ILCodeStream* pcsUnmarshal = psl->GetUnmarshalCodeStream();
2553 if (fManagedToNative && !byref)
2555 pcsMarshal->SetStubTargetArgType(ELEMENT_TYPE_I);
2558 // HandleRefs are valuetypes, so pinning is not needed.
2559 // The argument address is on the stack and will not move.
2560 mdFieldDef handleField = pcsDispatch->GetToken(MscorlibBinder::GetField(FIELD__HANDLE_REF__HANDLE));
2561 pcsDispatch->EmitLDARG(argidx);
2562 pcsDispatch->EmitLDFLD(handleField);
2564 mdFieldDef wrapperField = pcsUnmarshal->GetToken(MscorlibBinder::GetField(FIELD__HANDLE_REF__WRAPPER));
2565 pcsUnmarshal->EmitLDARG(argidx);
2566 pcsUnmarshal->EmitLDFLD(wrapperField);
2567 pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
2573 *pResID = IDS_EE_BADMARSHAL_HANDLEREFRESTRICTION;
2578 MarshalerOverrideStatus ILHandleRefMarshaler::ReturnOverride(NDirectStubLinker* psl,
2579 BOOL fManagedToNative,
2581 OverrideProcArgs* pargs,
2592 *pResID = IDS_EE_BADMARSHAL_HANDLEREFRESTRICTION;
2596 LocalDesc ILSafeHandleMarshaler::GetManagedType()
2598 STANDARD_VM_CONTRACT;
2600 return LocalDesc(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE));
2603 LocalDesc ILSafeHandleMarshaler::GetNativeType()
2605 LIMITED_METHOD_CONTRACT;
2607 return LocalDesc(ELEMENT_TYPE_I);
2610 bool ILSafeHandleMarshaler::NeedsClearNative()
2612 LIMITED_METHOD_CONTRACT;
2616 void ILSafeHandleMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
2618 STANDARD_VM_CONTRACT;
2620 _ASSERTE(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
2622 // call StubHelpers::SafeHandleRelease
2623 EmitLoadManagedValue(pslILEmit);
2624 pslILEmit->EmitCALL(METHOD__STUBHELPERS__SAFE_HANDLE_RELEASE, 1, 0);
2627 void ILSafeHandleMarshaler::EmitMarshalArgumentCLRToNative()
2632 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
2636 EmitSetupSigAndDefaultHomesCLRToNative();
2638 // by-value CLR-to-native SafeHandle is always passed in-only regardless of [In], [Out]
2639 // marshal and cleanup communicate via an extra local and are both emitted in this method
2641 // bool <dwHandleAddRefedLocalNum> = false
2642 ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream();
2643 DWORD dwHandleAddRefedLocalNum = pcsSetup->NewLocal(ELEMENT_TYPE_BOOLEAN);
2645 pcsSetup->EmitLDC(0);
2646 pcsSetup->EmitSTLOC(dwHandleAddRefedLocalNum);
2648 // <nativeHandle> = StubHelpers::SafeHandleAddRef(<managedSH>, ref <dwHandleAddRefedLocalNum>)
2649 EmitLoadManagedValue(m_pcsMarshal);
2650 m_pcsMarshal->EmitLDLOCA(dwHandleAddRefedLocalNum);
2651 m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__SAFE_HANDLE_ADD_REF, 2, 1);
2652 EmitStoreNativeValue(m_pcsMarshal);
2655 // if (<dwHandleAddRefedLocalNum>) StubHelpers.SafeHandleRelease(<managedSH>)
2656 ILCodeStream *pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
2657 ILCodeLabel *pSkipClearNativeLabel = pcsCleanup->NewCodeLabel();
2659 pcsCleanup->EmitLDLOC(dwHandleAddRefedLocalNum);
2660 pcsCleanup->EmitBRFALSE(pSkipClearNativeLabel);
2662 EmitClearNativeTemp(pcsCleanup);
2663 m_pslNDirect->SetCleanupNeeded();
2665 pcsCleanup->EmitLabel(pSkipClearNativeLabel);
2668 MarshalerOverrideStatus ILSafeHandleMarshaler::ArgumentOverride(NDirectStubLinker* psl,
2672 BOOL fManagedToNative,
2673 OverrideProcArgs* pargs,
2676 UINT nativeStackOffset)
2686 ILCodeStream* pslIL = psl->GetMarshalCodeStream();
2687 ILCodeStream* pslILDispatch = psl->GetDispatchCodeStream();
2689 if (fManagedToNative)
2693 pslIL->SetStubTargetArgType(ELEMENT_TYPE_I);
2695 // The specific SafeHandle subtype we're dealing with here.
2696 MethodTable *pHandleType = pargs->m_pMT;
2698 // Out SafeHandle parameters must not be abstract.
2699 if (fout && pHandleType->IsAbstract())
2701 *pResID = IDS_EE_BADMARSHAL_ABSTRACTOUTSAFEHANDLE;
2705 // We rely on the SafeHandle having a default constructor.
2706 if (!pHandleType->HasDefaultConstructor())
2708 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
2709 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
2712 // Grab the token for the native handle field embedded inside the SafeHandle. We'll be using it to direct access the
2713 // native handle later.
2714 mdToken tkNativeHandleField = pslIL->GetToken(MscorlibBinder::GetField(FIELD__SAFE_HANDLE__HANDLE));
2716 // The high level logic (note that the parameter may be in, out or both):
2717 // 1) If this is an input parameter we need to AddRef the SafeHandle and schedule a Release cleanup item.
2718 // 2) If this is an output parameter we need to preallocate a SafeHandle to wrap the new native handle value. We
2719 // must allocate this before the native call to avoid a failure point when we already have a native resource
2720 // allocated. We must allocate a new SafeHandle even if we have one on input since both input and output native
2721 // handles need to be tracked and released by a SafeHandle.
2722 // 3) Initialize a local IntPtr that will be passed to the native call. If we have an input SafeHandle the value
2723 // comes from there otherwise we get it from the new SafeHandle (which is guaranteed to be initialized to an
2724 // invalid handle value).
2725 // 4) If this is a out parameter we also store the original handle value (that we just computed above) in a local
2727 // 5) After the native call, if this is an output parameter and the handle value we passed to native differs from
2728 // the local copy we made then the new handle value is written into the output SafeHandle and that SafeHandle
2729 // is propagated back to the caller.
2732 DWORD dwInputHandleLocal = 0; // The input safe handle (in only)
2733 DWORD dwOutputHandleLocal = 0; // The output safe handle (out only)
2734 DWORD dwOldNativeHandleLocal = 0; // The original native handle value for comparison (out only)
2735 DWORD dwNativeHandleLocal; // The input (and possibly updated) native handle value
2739 LocalDesc locInputHandle(pHandleType);
2740 dwInputHandleLocal = pslIL->NewLocal(locInputHandle);
2744 LocalDesc locOutputHandle(pHandleType);
2745 dwOutputHandleLocal = pslIL->NewLocal(locOutputHandle);
2747 dwOldNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
2750 dwNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
2752 // Call StubHelpers.AddToCleanupList to atomically AddRef incoming SafeHandle and schedule a cleanup work item to
2753 // perform Release after the call. The helper also returns the native handle value to us so take the opportunity
2754 // to store this in the NativeHandle local we've allocated.
2757 pslIL->EmitLDARG(argidx);
2758 pslIL->EmitLDIND_REF();
2760 pslIL->EmitSTLOC(dwInputHandleLocal);
2762 // Release the original input SafeHandle after the call.
2763 psl->LoadCleanupWorkList(pslIL);
2764 pslIL->EmitLDLOC(dwInputHandleLocal);
2766 // This is realiable, i.e. the cleanup will happen if and only if the SH was actually AddRef'ed.
2767 pslIL->EmitCALL(METHOD__STUBHELPERS__ADD_TO_CLEANUP_LIST_SAFEHANDLE, 2, 1);
2769 pslIL->EmitSTLOC(dwNativeHandleLocal);
2773 // For output parameters we need to allocate a new SafeHandle to hold the result.
2776 MethodDesc* pMDCtor = pHandleType->GetDefaultConstructor();
2777 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
2778 pslIL->EmitSTLOC(dwOutputHandleLocal);
2780 // If we didn't provide an input handle then we initialize the NativeHandle local with the (initially invalid)
2781 // handle field set up inside the output handle by the constructor.
2784 pslIL->EmitLDLOC(dwOutputHandleLocal);
2785 pslIL->EmitLDFLD(tkNativeHandleField);
2786 pslIL->EmitSTLOC(dwNativeHandleLocal);
2789 // Remember the handle value we start out with so we know whether to back propagate after the native call.
2790 pslIL->EmitLDLOC(dwNativeHandleLocal);
2791 pslIL->EmitSTLOC(dwOldNativeHandleLocal);
2794 // Leave the address of the native handle local as the argument to the native method.
2795 pslILDispatch->EmitLDLOCA(dwNativeHandleLocal);
2797 // On the output side we only backpropagate the native handle into the output SafeHandle and the output SafeHandle
2798 // to the caller if the native handle actually changed (otherwise we can end up with two SafeHandles wrapping the
2799 // same native handle, which is bad).
2802 // We will use cleanup stream to avoid leaking the handle on thread abort.
2803 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx);
2805 psl->SetCleanupNeeded();
2806 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
2808 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
2810 psl->EmitCheckForArgCleanup(pslCleanupIL,
2811 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx,
2812 NDirectStubLinker::BranchIfNotMarshaled,
2815 // If this is an [in, out] handle check if the native handles have changed. If not we're finished.
2818 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
2819 pslCleanupIL->EmitLDLOC(dwOldNativeHandleLocal);
2820 pslCleanupIL->EmitCEQ();
2821 pslCleanupIL->EmitBRTRUE(pDoneLabel);
2824 // Propagate the native handle into the output SafeHandle.
2825 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
2826 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
2827 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
2829 // Propagate the output SafeHandle back to the caller.
2830 pslCleanupIL->EmitLDARG(argidx);
2831 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
2832 pslCleanupIL->EmitSTIND_REF();
2834 pslCleanupIL->EmitLabel(pDoneLabel);
2839 // Avoid using the cleanup list in this common case for perf reasons (cleanup list is
2840 // unmanaged and destroying it means excessive managed<->native transitions; in addition,
2841 // as X86 IL stubs do not use interop frames, there's nothing protecting the cleanup list
2842 // and the SafeHandle references must be GC handles which does not help perf either).
2844 // This code path generates calls to StubHelpers.SafeHandleAddRef and SafeHandleRelease.
2845 // NICE: Could SafeHandle.DangerousAddRef and DangerousRelease be implemented in managed?
2846 return HANDLEASNORMAL;
2853 *pResID = IDS_EE_BADMARSHAL_SAFEHANDLENATIVETOCOM;
2858 //---------------------------------------------------------------------------------------
2860 MarshalerOverrideStatus
2861 ILSafeHandleMarshaler::ReturnOverride(
2862 NDirectStubLinker * psl,
2863 BOOL fManagedToNative,
2865 OverrideProcArgs * pargs,
2873 PRECONDITION(CheckPointer(psl));
2874 PRECONDITION(CheckPointer(pargs));
2875 PRECONDITION(CheckPointer(pResID));
2879 ILCodeStream * pslIL = psl->GetMarshalCodeStream();
2880 ILCodeStream * pslPostIL = psl->GetReturnUnmarshalCodeStream();
2881 ILCodeStream * pslILDispatch = psl->GetDispatchCodeStream();
2883 if (!fManagedToNative)
2885 *pResID = IDS_EE_BADMARSHAL_RETURNSHCOMTONATIVE;
2889 // Returned SafeHandle parameters must not be abstract.
2890 if (pargs->m_pMT->IsAbstract())
2892 *pResID = IDS_EE_BADMARSHAL_ABSTRACTRETSAFEHANDLE;
2896 // 1) create local for new safehandle
2897 // 2) prealloc a safehandle
2898 // 3) create local to hold returned handle
2899 // 4) [byref] add byref IntPtr to native sig
2900 // 5) [byref] pass address of local as last arg
2901 // 6) store return value in safehandle
2903 // 1) create local for new safehandle
2904 MethodTable * pMT = pargs->m_pMT;
2905 LocalDesc locDescReturnHandle(pMT);
2906 DWORD dwReturnHandleLocal;
2908 dwReturnHandleLocal = pslIL->NewLocal(locDescReturnHandle);
2910 if (!pMT->HasDefaultConstructor())
2912 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
2913 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
2916 // 2) prealloc a safehandle
2917 MethodDesc* pMDCtor = pMT->GetDefaultConstructor();
2918 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
2919 pslIL->EmitSTLOC(dwReturnHandleLocal);
2921 mdToken tkNativeHandleField = pslPostIL->GetToken(MscorlibBinder::GetField(FIELD__SAFE_HANDLE__HANDLE));
2923 // 3) create local to hold returned handle
2924 DWORD dwReturnNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
2928 // initialize the native handle
2929 pslIL->EmitLDLOC(dwReturnHandleLocal);
2930 pslIL->EmitLDFLD(tkNativeHandleField);
2931 pslIL->EmitSTLOC(dwReturnNativeHandleLocal);
2933 pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I4); // native method returns an HRESULT
2935 // 4) [byref] add byref IntPtr to native sig
2936 locDescReturnHandle.ElementType[0] = ELEMENT_TYPE_BYREF;
2937 locDescReturnHandle.ElementType[1] = ELEMENT_TYPE_I;
2938 locDescReturnHandle.cbType = 2;
2939 pslIL->SetStubTargetArgType(&locDescReturnHandle, false); // extra arg is a byref IntPtr
2941 // 5) [byref] pass address of local as last arg
2942 pslILDispatch->EmitLDLOCA(dwReturnNativeHandleLocal);
2944 // We will use cleanup stream to avoid leaking the handle on thread abort.
2945 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL);
2947 psl->SetCleanupNeeded();
2948 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
2949 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
2951 psl->EmitCheckForArgCleanup(pslCleanupIL,
2952 NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL,
2953 NDirectStubLinker::BranchIfNotMarshaled,
2956 // 6) store return value in safehandle
2957 pslCleanupIL->EmitLDLOC(dwReturnHandleLocal);
2958 pslCleanupIL->EmitLDLOC(dwReturnNativeHandleLocal);
2959 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
2960 pslCleanupIL->EmitLabel(pDoneLabel);
2962 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
2966 pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I);
2967 pslPostIL->EmitSTLOC(dwReturnNativeHandleLocal);
2969 // 6) store return value in safehandle
2970 // The thread abort logic knows that it must not interrupt the stub so we will
2971 // always be able to execute this sequence after returning from the call.
2972 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
2973 pslPostIL->EmitLDLOC(dwReturnNativeHandleLocal);
2974 pslPostIL->EmitSTFLD(tkNativeHandleField);
2975 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
2979 } // ILSafeHandleMarshaler::ReturnOverride
2982 //---------------------------------------------------------------------------------------
2984 MarshalerOverrideStatus ILCriticalHandleMarshaler::ArgumentOverride(NDirectStubLinker* psl,
2988 BOOL fManagedToNative,
2989 OverrideProcArgs* pargs,
2992 UINT nativeStackOffset)
3002 ILCodeStream* pslIL = psl->GetMarshalCodeStream();
3003 ILCodeStream* pslPostIL = psl->GetUnmarshalCodeStream();
3004 ILCodeStream* pslILDispatch = psl->GetDispatchCodeStream();
3006 if (fManagedToNative)
3008 pslIL->SetStubTargetArgType(ELEMENT_TYPE_I);
3010 // Grab the token for the native handle field embedded inside the CriticalHandle. We'll be using it to direct access
3011 // the native handle later.
3012 mdToken tkNativeHandleField = pslIL->GetToken(MscorlibBinder::GetField(FIELD__CRITICAL_HANDLE__HANDLE));
3016 // The specific CriticalHandle subtype we're dealing with here.
3017 MethodTable *pHandleType = pargs->m_pMT;
3019 // Out CriticalHandle parameters must not be abstract.
3020 if (fout && pHandleType->IsAbstract())
3022 *pResID = IDS_EE_BADMARSHAL_ABSTRACTOUTCRITICALHANDLE;
3026 // We rely on the CriticalHandle having a default constructor.
3027 if (!pHandleType->HasDefaultConstructor())
3029 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
3030 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
3033 // The high level logic (note that the parameter may be in, out or both):
3034 // 1) If this is an output parameter we need to preallocate a CriticalHandle to wrap the new native handle value. We
3035 // must allocate this before the native call to avoid a failure point when we already have a native resource
3036 // allocated. We must allocate a new CriticalHandle even if we have one on input since both input and output native
3037 // handles need to be tracked and released by a CriticalHandle.
3038 // 2) Initialize a local IntPtr that will be passed to the native call. If we have an input CriticalHandle the value
3039 // comes from there otherwise we get it from the new CriticalHandle (which is guaranteed to be initialized to an
3040 // invalid handle value).
3041 // 3) If this is a out parameter we also store the original handle value (that we just computed above) in a local
3043 // 4) After the native call, if this is an output parameter and the handle value we passed to native differs from
3044 // the local copy we made then the new handle value is written into the output CriticalHandle and that
3045 // CriticalHandle is propagated back to the caller.
3048 LocalDesc locOutputHandle;
3049 DWORD dwOutputHandleLocal = 0; // The output critical handle (out only)
3050 DWORD dwOldNativeHandleLocal = 0; // The original native handle value for comparison (out only)
3051 DWORD dwNativeHandleLocal; // The input (and possibly updated) native handle value
3055 locOutputHandle.ElementType[0] = ELEMENT_TYPE_INTERNAL;
3056 locOutputHandle.cbType = 1;
3057 locOutputHandle.InternalToken = pHandleType;
3059 dwOutputHandleLocal = pslIL->NewLocal(locOutputHandle);
3061 dwOldNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
3064 dwNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
3067 // If we have an input CriticalHandle then initialize our NativeHandle local with it.
3070 pslIL->EmitLDARG(argidx);
3071 pslIL->EmitLDIND_REF();
3072 pslIL->EmitLDFLD(tkNativeHandleField);
3073 pslIL->EmitSTLOC(dwNativeHandleLocal);
3076 // For output parameters we need to allocate a new CriticalHandle to hold the result.
3079 MethodDesc* pMDCtor = pHandleType->GetDefaultConstructor();
3080 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
3081 pslIL->EmitSTLOC(dwOutputHandleLocal);
3083 // If we didn't provide an input handle then we initialize the NativeHandle local with the (initially invalid)
3084 // handle field set up inside the output handle by the constructor.
3087 pslIL->EmitLDLOC(dwOutputHandleLocal);
3088 pslIL->EmitLDFLD(tkNativeHandleField);
3089 pslIL->EmitSTLOC(dwNativeHandleLocal);
3092 // Remember the handle value we start out with so we know whether to back propagate after the native call.
3093 pslIL->EmitLDLOC(dwNativeHandleLocal);
3094 pslIL->EmitSTLOC(dwOldNativeHandleLocal);
3097 // Leave the address of the native handle local as the argument to the native method.
3098 pslILDispatch->EmitLDLOCA(dwNativeHandleLocal);
3102 // prevent the CriticalHandle from being finalized during the call-out to native
3103 pslPostIL->EmitLDARG(argidx);
3104 pslPostIL->EmitLDIND_REF();
3105 pslPostIL->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
3108 // On the output side we only backpropagate the native handle into the output CriticalHandle and the output
3109 // CriticalHandle to the caller if the native handle actually changed (otherwise we can end up with two
3110 // CriticalHandles wrapping the same native handle, which is bad).
3113 // We will use cleanup stream to avoid leaking the handle on thread abort.
3114 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx);
3116 psl->SetCleanupNeeded();
3117 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
3119 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
3121 psl->EmitCheckForArgCleanup(pslCleanupIL,
3122 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx,
3123 NDirectStubLinker::BranchIfNotMarshaled,
3126 // If this is an [in, out] handle check if the native handles have changed. If not we're finished.
3129 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
3130 pslCleanupIL->EmitLDLOC(dwOldNativeHandleLocal);
3131 pslCleanupIL->EmitCEQ();
3132 pslCleanupIL->EmitBRTRUE(pDoneLabel);
3135 // Propagate the native handle into the output CriticalHandle.
3136 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
3137 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
3138 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
3140 // Propagate the output CriticalHandle back to the caller.
3141 pslCleanupIL->EmitLDARG(argidx);
3142 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
3143 pslCleanupIL->EmitSTIND_REF();
3145 pslCleanupIL->EmitLabel(pDoneLabel);
3150 pslILDispatch->EmitLDARG(argidx);
3151 pslILDispatch->EmitLDFLD(tkNativeHandleField);
3153 // prevent the CriticalHandle from being finalized during the call-out to native
3154 pslPostIL->EmitLDARG(argidx);
3155 pslPostIL->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
3162 *pResID = IDS_EE_BADMARSHAL_CRITICALHANDLENATIVETOCOM;
3167 //---------------------------------------------------------------------------------------
3169 MarshalerOverrideStatus
3170 ILCriticalHandleMarshaler::ReturnOverride(
3171 NDirectStubLinker * psl,
3172 BOOL fManagedToNative,
3174 OverrideProcArgs * pargs,
3182 PRECONDITION(CheckPointer(psl));
3183 PRECONDITION(CheckPointer(pargs));
3184 PRECONDITION(CheckPointer(pResID));
3188 if (!fManagedToNative)
3190 *pResID = IDS_EE_BADMARSHAL_RETURNSHCOMTONATIVE;
3194 // Returned CriticalHandle parameters must not be abstract.
3195 if (pargs->m_pMT->IsAbstract())
3197 *pResID = IDS_EE_BADMARSHAL_ABSTRACTRETCRITICALHANDLE;
3201 ILCodeStream * pslIL = psl->GetMarshalCodeStream();
3202 ILCodeStream * pslPostIL = psl->GetReturnUnmarshalCodeStream();
3203 ILCodeStream * pslILDispatch = psl->GetDispatchCodeStream();
3205 // 1) create local for new criticalhandle
3206 // 2) prealloc a criticalhandle
3207 // 3) create local to hold returned handle
3208 // 4) [byref] add byref IntPtr to native sig
3209 // 5) [byref] pass address of local as last arg
3210 // 6) store return value in criticalhandle
3212 // 1) create local for new criticalhandle
3213 MethodTable * pMT = pargs->m_pMT;
3214 LocalDesc locDescReturnHandle(pMT);
3215 DWORD dwReturnHandleLocal;
3217 dwReturnHandleLocal = pslIL->NewLocal(locDescReturnHandle);
3219 if (!pMT->HasDefaultConstructor())
3221 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
3222 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
3225 // 2) prealloc a criticalhandle
3226 MethodDesc * pMDCtor = pMT->GetDefaultConstructor();
3227 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
3228 pslIL->EmitSTLOC(dwReturnHandleLocal);
3230 mdToken tkNativeHandleField = pslPostIL->GetToken(MscorlibBinder::GetField(FIELD__CRITICAL_HANDLE__HANDLE));
3232 // 3) create local to hold returned handle
3233 DWORD dwReturnNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
3237 // initialize the native handle
3238 pslIL->EmitLDLOC(dwReturnHandleLocal);
3239 pslIL->EmitLDFLD(tkNativeHandleField);
3240 pslIL->EmitSTLOC(dwReturnNativeHandleLocal);
3242 pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I4); // native method returns an HRESULT
3244 // 4) [byref] add byref IntPtr to native sig
3245 locDescReturnHandle.ElementType[0] = ELEMENT_TYPE_BYREF;
3246 locDescReturnHandle.ElementType[1] = ELEMENT_TYPE_I;
3247 locDescReturnHandle.cbType = 2;
3248 pslIL->SetStubTargetArgType(&locDescReturnHandle, false); // extra arg is a byref IntPtr
3250 // 5) [byref] pass address of local as last arg
3251 pslILDispatch->EmitLDLOCA(dwReturnNativeHandleLocal);
3253 // We will use cleanup stream to avoid leaking the handle on thread abort.
3254 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL);
3256 psl->SetCleanupNeeded();
3257 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
3258 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
3260 // 6) store return value in criticalhandle
3261 psl->EmitCheckForArgCleanup(pslCleanupIL,
3262 NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL,
3263 NDirectStubLinker::BranchIfNotMarshaled,
3266 pslCleanupIL->EmitLDLOC(dwReturnHandleLocal);
3267 pslCleanupIL->EmitLDLOC(dwReturnNativeHandleLocal);
3268 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
3269 pslCleanupIL->EmitLabel(pDoneLabel);
3271 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
3275 pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I);
3276 pslPostIL->EmitSTLOC(dwReturnNativeHandleLocal);
3278 // 6) store return value in criticalhandle
3279 // The thread abort logic knows that it must not interrupt the stub so we will
3280 // always be able to execute this sequence after returning from the call.
3281 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
3282 pslPostIL->EmitLDLOC(dwReturnNativeHandleLocal);
3283 pslPostIL->EmitSTFLD(tkNativeHandleField);
3284 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
3288 } // ILCriticalHandleMarshaler::ReturnOverride
3291 LocalDesc ILArgIteratorMarshaler::GetNativeType()
3293 LIMITED_METHOD_CONTRACT;
3295 return LocalDesc(ELEMENT_TYPE_I); // va_list
3298 LocalDesc ILArgIteratorMarshaler::GetManagedType()
3300 STANDARD_VM_CONTRACT;
3302 return LocalDesc(MscorlibBinder::GetClass(CLASS__ARG_ITERATOR));
3305 bool ILArgIteratorMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3307 LIMITED_METHOD_CONTRACT;
3309 if (IsByref(dwMarshalFlags))
3311 *pErrorResID = IDS_EE_BADMARSHAL_ARGITERATORRESTRICTION;
3318 void ILArgIteratorMarshaler::EmitMarshalArgumentCLRToNative()
3323 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3327 EmitSetupSigAndDefaultHomesCLRToNative();
3333 // Allocate enough memory for va_list
3334 DWORD dwVaListSizeLocal = m_pcsMarshal->NewLocal(LocalDesc(ELEMENT_TYPE_U4));
3335 EmitLoadManagedHomeAddr(m_pcsMarshal);
3336 m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__CALC_VA_LIST_SIZE, 1, 1);
3337 m_pcsMarshal->EmitSTLOC(dwVaListSizeLocal);
3338 m_pcsMarshal->EmitLDLOC(dwVaListSizeLocal);
3339 m_pcsMarshal->EmitLOCALLOC();
3340 EmitStoreNativeValue(m_pcsMarshal);
3342 // void MarshalToUnmanagedVaListInternal(cbVaListSize, va_list, VARARGS* data)
3343 EmitLoadNativeValue(m_pcsMarshal);
3344 m_pcsMarshal->EmitLDLOC(dwVaListSizeLocal);
3345 EmitLoadManagedHomeAddr(m_pcsMarshal);
3346 m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__MARSHAL_TO_UNMANAGED_VA_LIST_INTERNAL, 3, 0);
3349 void ILArgIteratorMarshaler::EmitMarshalArgumentNativeToCLR()
3354 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3358 EmitSetupSigAndDefaultHomesNativeToCLR();
3360 EmitLoadNativeValue(m_pcsMarshal);
3361 EmitLoadManagedHomeAddr(m_pcsMarshal);
3363 // void MarshalToManagedVaList(va_list va, VARARGS *dataout)
3364 m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__MARSHAL_TO_MANAGED_VA_LIST_INTERNAL, 2, 0);
3368 LocalDesc ILArrayWithOffsetMarshaler::GetNativeType()
3370 LIMITED_METHOD_CONTRACT;
3372 return LocalDesc(ELEMENT_TYPE_I);
3375 LocalDesc ILArrayWithOffsetMarshaler::GetManagedType()
3377 STANDARD_VM_CONTRACT;
3379 return LocalDesc(MscorlibBinder::GetClass(CLASS__ARRAY_WITH_OFFSET));
3382 bool ILArrayWithOffsetMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3384 LIMITED_METHOD_CONTRACT;
3386 if (IsCLRToNative(dwMarshalFlags) && !IsByref(dwMarshalFlags) && IsIn(dwMarshalFlags) && IsOut(dwMarshalFlags))
3391 *pErrorResID = IDS_EE_BADMARSHAL_AWORESTRICTION;
3396 void ILArrayWithOffsetMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
3402 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwCountLocalNum);
3403 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwOffsetLocalNum);
3404 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwPinnedLocalNum);
3408 int tokArrayWithOffset_m_array = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_ARRAY));
3409 int tokArrayWithOffset_m_count = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_COUNT));
3411 ILCodeLabel* pNonNullLabel = pslILEmit->NewCodeLabel();
3412 ILCodeLabel* pSlowAllocPathLabel = pslILEmit->NewCodeLabel();
3413 ILCodeLabel* pDoneLabel = pslILEmit->NewCodeLabel();
3415 m_dwCountLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
3418 // Convert the space
3421 EmitLoadManagedValue(pslILEmit);
3422 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3423 pslILEmit->EmitBRTRUE(pNonNullLabel);
3425 pslILEmit->EmitLoadNullPtr();
3426 pslILEmit->EmitBR(pDoneLabel);
3427 pslILEmit->EmitLabel(pNonNullLabel);
3429 EmitLoadManagedValue(pslILEmit);
3430 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_count);
3431 pslILEmit->EmitDUP();
3432 pslILEmit->EmitSTLOC(m_dwCountLocalNum);
3433 pslILEmit->EmitDUP();
3434 pslILEmit->EmitLDC(s_cbStackAllocThreshold);
3435 pslILEmit->EmitCGT_UN();
3436 pslILEmit->EmitBRTRUE(pSlowAllocPathLabel);
3439 pslILEmit->EmitLOCALLOC();
3441 pslILEmit->EmitBR(pDoneLabel);
3442 pslILEmit->EmitLabel(pSlowAllocPathLabel);
3445 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
3447 pslILEmit->EmitLabel(pDoneLabel);
3448 EmitStoreNativeValue(pslILEmit);
3451 // Convert the contents
3454 int tokArrayWithOffset_m_offset = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_OFFSET));
3456 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
3458 LocalDesc locDescPinned;
3459 locDescPinned.cbType = 2;
3460 locDescPinned.ElementType[0] = ELEMENT_TYPE_PINNED;
3461 locDescPinned.ElementType[1] = ELEMENT_TYPE_OBJECT;
3462 m_dwPinnedLocalNum = pslILEmit->NewLocal(locDescPinned);
3463 m_dwOffsetLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
3465 EmitLoadManagedValue(pslILEmit);
3466 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3467 pslILEmit->EmitBRFALSE(pNullRefLabel);
3469 EmitLoadManagedValue(pslILEmit);
3470 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3471 pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3473 EmitLoadNativeValue(pslILEmit); // dest
3475 pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3476 pslILEmit->EmitCONV_I();
3477 pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3478 pslILEmit->EmitCALL(METHOD__ARRAY__GET_DATA_PTR_OFFSET_INTERNAL, 1, 1);
3479 pslILEmit->EmitADD(); // TODO Phase5: Use UnsafeAddrOfPinnedArrayElement
3481 EmitLoadManagedValue(pslILEmit);
3482 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_offset);
3483 pslILEmit->EmitDUP();
3484 pslILEmit->EmitSTLOC(m_dwOffsetLocalNum);
3485 pslILEmit->EmitADD(); // src
3486 pslILEmit->EmitLDLOC(m_dwCountLocalNum); // len
3488 // static void Memcpy(byte* dest, byte* src, int len)
3489 pslILEmit->EmitCALL(METHOD__BUFFER__MEMCPY, 3, 0);
3491 pslILEmit->EmitLDNULL();
3492 pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3494 pslILEmit->EmitLabel(pNullRefLabel);
3497 void ILArrayWithOffsetMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
3503 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED != m_dwCountLocalNum);
3504 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED != m_dwOffsetLocalNum);
3505 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED != m_dwPinnedLocalNum);
3509 int tokArrayWithOffset_m_array = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_ARRAY));
3511 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
3513 EmitLoadManagedValue(pslILEmit);
3514 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3515 pslILEmit->EmitBRFALSE(pNullRefLabel);
3517 EmitLoadManagedValue(pslILEmit);
3518 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3519 pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3521 pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3522 pslILEmit->EmitCONV_I();
3523 pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3524 pslILEmit->EmitCALL(METHOD__ARRAY__GET_DATA_PTR_OFFSET_INTERNAL, 1, 1);
3525 pslILEmit->EmitADD(); // TODO Phase5: Use UnsafeAddrOfPinnedArrayElement
3527 pslILEmit->EmitLDLOC(m_dwOffsetLocalNum);
3528 pslILEmit->EmitADD(); // dest
3530 EmitLoadNativeValue(pslILEmit); // src
3532 pslILEmit->EmitLDLOC(m_dwCountLocalNum); // len
3534 // static void Memcpy(byte* dest, byte* src, int len)
3535 pslILEmit->EmitCALL(METHOD__BUFFER__MEMCPY, 3, 0);
3537 pslILEmit->EmitLDNULL();
3538 pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3540 pslILEmit->EmitLabel(pNullRefLabel);
3543 void ILArrayWithOffsetMarshaler::EmitClearNativeTemp(ILCodeStream* pslILEmit)
3545 STANDARD_VM_CONTRACT;
3547 ILCodeLabel* pDoneLabel = pslILEmit->NewCodeLabel();
3549 pslILEmit->EmitLDLOC(m_dwCountLocalNum);
3550 pslILEmit->EmitLDC(s_cbStackAllocThreshold);
3551 pslILEmit->EmitCGT_UN();
3552 pslILEmit->EmitBRFALSE(pDoneLabel);
3555 EmitLoadNativeValue(pslILEmit);
3556 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
3558 pslILEmit->EmitLabel(pDoneLabel);
3561 LocalDesc ILAsAnyMarshalerBase::GetNativeType()
3563 LIMITED_METHOD_CONTRACT;
3565 return LocalDesc(ELEMENT_TYPE_I);
3568 LocalDesc ILAsAnyMarshalerBase::GetManagedType()
3570 LIMITED_METHOD_CONTRACT;
3572 return LocalDesc(ELEMENT_TYPE_OBJECT);
3575 bool ILAsAnyMarshalerBase::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3577 WRAPPER_NO_CONTRACT;
3579 if (IsCLRToNative(dwMarshalFlags) && !IsByref(dwMarshalFlags))
3584 *pErrorResID = IDS_EE_BADMARSHAL_ASANYRESTRICTION;
3588 bool ILAsAnyMarshalerBase::SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3590 LIMITED_METHOD_CONTRACT;
3591 *pErrorResID = IDS_EE_BADMARSHAL_ASANYRESTRICTION;
3595 void ILAsAnyMarshalerBase::EmitMarshalArgumentCLRToNative()
3600 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3601 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwMarshalerLocalNum);
3605 EmitSetupSigAndDefaultHomesCLRToNative();
3607 BYTE inout = (IsIn(m_dwMarshalFlags) ? ML_IN : 0) | (IsOut(m_dwMarshalFlags) ? ML_OUT : 0);
3608 BYTE fIsAnsi = IsAnsi() ? 1 : 0;
3609 BYTE fBestFit = m_pargs->m_pMarshalInfo->GetBestFitMapping();
3610 BYTE fThrow = m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar();
3614 dwFlags |= inout << 24;
3615 dwFlags |= fIsAnsi << 16;
3616 dwFlags |= fThrow << 8;
3617 dwFlags |= fBestFit << 0;
3623 LocalDesc marshalerType(MscorlibBinder::GetClass(CLASS__ASANY_MARSHALER));
3624 m_dwMarshalerLocalNum = m_pcsMarshal->NewLocal(marshalerType);
3625 DWORD dwTmpLocalNum = m_pcsMarshal->NewLocal(ELEMENT_TYPE_I);
3627 m_pcsMarshal->EmitLDC(sizeof(MngdNativeArrayMarshaler));
3628 m_pcsMarshal->EmitLOCALLOC();
3629 m_pcsMarshal->EmitSTLOC(dwTmpLocalNum);
3631 // marshaler = new AsAnyMarshaler(local_buffer)
3632 m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3633 m_pcsMarshal->EmitINITOBJ(m_pcsMarshal->GetToken(marshalerType.InternalToken));
3635 m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3636 m_pcsMarshal->EmitLDLOC(dwTmpLocalNum);
3637 m_pcsMarshal->EmitCALL(METHOD__ASANY_MARSHALER__CTOR, 2, 0);
3639 // nativeValue = marshaler.ConvertToNative(managedValue, flags);
3640 m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3641 EmitLoadManagedValue(m_pcsMarshal);
3642 m_pcsMarshal->EmitLDC(dwFlags);
3643 m_pcsMarshal->EmitCALL(METHOD__ASANY_MARSHALER__CONVERT_TO_NATIVE, 3, 1);
3644 EmitStoreNativeValue(m_pcsMarshal);
3649 if (IsOut(m_dwMarshalFlags))
3651 // marshaler.ConvertToManaged(managedValue, nativeValue)
3652 m_pcsUnmarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3653 EmitLoadManagedValue(m_pcsUnmarshal);
3654 EmitLoadNativeValue(m_pcsUnmarshal);
3655 m_pcsUnmarshal->EmitCALL(METHOD__ASANY_MARSHALER__CONVERT_TO_MANAGED, 3, 0);
3661 EmitCleanupCLRToNativeTemp();
3664 bool ILAsAnyMarshalerBase::NeedsClearNative()
3666 LIMITED_METHOD_CONTRACT;
3670 void ILAsAnyMarshalerBase::EmitClearNativeTemp(ILCodeStream* pslILEmit)
3672 STANDARD_VM_CONTRACT;
3674 // marshaler.ClearNative(nativeHome)
3675 pslILEmit->EmitLDLOCA(m_dwMarshalerLocalNum);
3676 EmitLoadNativeValue(pslILEmit);
3677 pslILEmit->EmitCALL(METHOD__ASANY_MARSHALER__CLEAR_NATIVE, 2, 0);
3680 // we can get away with putting the GetManagedType and GetNativeType on ILMngdMarshaler because
3681 // currently it is only used for reference marshaling where this is appropriate. If it became
3682 // used for something else, we would want to move this down in the inheritence tree..
3683 LocalDesc ILMngdMarshaler::GetNativeType()
3685 LIMITED_METHOD_CONTRACT;
3687 return LocalDesc(ELEMENT_TYPE_I);
3690 LocalDesc ILMngdMarshaler::GetManagedType()
3692 LIMITED_METHOD_CONTRACT;
3694 return LocalDesc(ELEMENT_TYPE_OBJECT);
3697 void ILMngdMarshaler::EmitCallMngdMarshalerMethod(ILCodeStream* pslILEmit, MethodDesc *pMD)
3699 STANDARD_VM_CONTRACT;
3704 UINT numArgs = sig.NumFixedArgs();
3708 EmitLoadMngdMarshaler(pslILEmit);
3712 _ASSERTE(numArgs == 2);
3715 EmitLoadManagedHomeAddr(pslILEmit);
3716 EmitLoadNativeHomeAddr(pslILEmit);
3718 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), numArgs, 0);
3722 bool ILNativeArrayMarshaler::UsePinnedArraySpecialCase()
3724 if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && (NULL == OleVariant::GetMarshalerForVarType(m_pargs->na.m_vt, TRUE)))
3732 void ILNativeArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
3734 STANDARD_VM_CONTRACT;
3736 if (UsePinnedArraySpecialCase())
3741 m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
3743 pslILEmit->EmitLDC(sizeof(MngdNativeArrayMarshaler));
3744 pslILEmit->EmitLOCALLOC();
3745 pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
3747 CREATE_MARSHALER_CARRAY_OPERANDS mops;
3748 m_pargs->m_pMarshalInfo->GetMops(&mops);
3750 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
3752 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(mops.methodTable));
3753 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
3755 DWORD dwFlags = mops.elementType;
3756 dwFlags |= (((DWORD)mops.bestfitmapping) << 16);
3757 dwFlags |= (((DWORD)mops.throwonunmappablechar) << 24);
3759 if (!IsCLRToNative(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
3761 // Unmanaged->managed in/out is the only case where we expect the native buffer to contain valid data.
3762 _ASSERTE((dwFlags & MngdNativeArrayMarshaler::FLAG_NATIVE_DATA_VALID) == 0);
3763 dwFlags |= MngdNativeArrayMarshaler::FLAG_NATIVE_DATA_VALID;
3766 pslILEmit->EmitLDC(dwFlags);
3768 pslILEmit->EmitCALL(METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CREATE_MARSHALER, 3, 0);
3772 void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNative()
3777 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3781 if (UsePinnedArraySpecialCase())
3784 // Replicate ML_PINNEDISOMORPHICARRAY_C2N_EXPRESS behavior -- note that this
3785 // gives in/out semantics "for free" even if the app doesn't specify one or
3786 // the other. Since there is no enforcement of this, apps blithely depend
3790 // The base offset should only be 0 for System.Array parameters for which
3791 // OleVariant::GetMarshalerForVarType(vt) should never return NULL.
3792 _ASSERTE(m_pargs->na.m_optionalbaseoffset != 0);
3794 EmitSetupSigAndDefaultHomesCLRToNative();
3796 LocalDesc managedType = GetManagedType();
3797 managedType.MakePinned();
3799 DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedType);
3800 ILCodeLabel* pNullRefLabel = m_pcsMarshal->NewCodeLabel();
3802 m_pcsMarshal->EmitLoadNullPtr();
3803 EmitStoreNativeValue(m_pcsMarshal);
3805 EmitLoadManagedValue(m_pcsMarshal);
3806 m_pcsMarshal->EmitBRFALSE(pNullRefLabel);
3808 EmitLoadManagedValue(m_pcsMarshal);
3809 m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
3810 m_pcsMarshal->EmitLDLOC(dwPinnedLocal);
3811 m_pcsMarshal->EmitCONV_I();
3812 m_pcsMarshal->EmitLDC(m_pargs->na.m_optionalbaseoffset);
3813 m_pcsMarshal->EmitADD();
3814 EmitStoreNativeValue(m_pcsMarshal);
3816 if (g_pConfig->InteropLogArguments())
3818 m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal);
3821 m_pcsMarshal->EmitLabel(pNullRefLabel);
3825 ILMngdMarshaler::EmitMarshalArgumentCLRToNative();
3830 // Peek at the SizeParamIndex argument
3831 // 1) See if the SizeParamIndex argument is being passed by ref
3832 // 2) Get the element type of SizeParamIndex argument
3834 BOOL ILNativeArrayMarshaler::CheckSizeParamIndexArg(
3835 const CREATE_MARSHALER_CARRAY_OPERANDS &mops,
3836 CorElementType *pElementType)
3843 PRECONDITION(m_pargs != NULL);
3844 PRECONDITION(m_pargs->m_pMarshalInfo != NULL);
3848 MethodDesc *pMD = m_pargs->m_pMarshalInfo->GetMethodDesc();
3851 Module *pModule = m_pargs->m_pMarshalInfo->GetModule();
3854 SigTypeContext emptyTypeContext; // this is an empty type context: ndirect and COM calls are guaranteed to not be generics.
3855 MetaSig msig(pMD->GetSignature(),
3860 // Go to the SizeParamIndex argument
3861 // Note that we already have check in place to make sure SizeParamIndex is within range
3863 if (msig.HasExplicitThis())
3866 for (int i = 0; i < mops.countParamIdx; ++i)
3871 SigPointer sigPointer = msig.GetArgProps();
3873 // Peek into the SizeParamIndex argument
3874 CorElementType elementType;
3875 IfFailThrow(sigPointer.PeekElemType(&elementType));
3877 if (elementType != ELEMENT_TYPE_BYREF)
3879 if (elementType == ELEMENT_TYPE_STRING ||
3880 elementType == ELEMENT_TYPE_ARRAY ||
3881 elementType == ELEMENT_TYPE_FNPTR ||
3882 elementType == ELEMENT_TYPE_OBJECT ||
3883 elementType == ELEMENT_TYPE_SZARRAY ||
3884 elementType == ELEMENT_TYPE_TYPEDBYREF)
3886 COMPlusThrow(kMarshalDirectiveException, IDS_EE_SIZECONTROLBADTYPE);
3889 *pElementType = elementType;
3893 // Get the real type
3894 IfFailThrow(sigPointer.GetElemType(NULL));
3895 IfFailThrow(sigPointer.PeekElemType(&elementType));
3897 // All the integral types are supported
3900 case ELEMENT_TYPE_I1:
3901 case ELEMENT_TYPE_U1:
3902 case ELEMENT_TYPE_I2:
3903 case ELEMENT_TYPE_U2:
3904 case ELEMENT_TYPE_I4:
3905 case ELEMENT_TYPE_U4:
3906 case ELEMENT_TYPE_I8:
3907 case ELEMENT_TYPE_U8:
3908 case ELEMENT_TYPE_I:
3909 case ELEMENT_TYPE_U:
3913 COMPlusThrow(kMarshalDirectiveException, IDS_EE_SIZECONTROLBADTYPE);
3916 *pElementType = elementType;
3921 // Calculate the number of elements and load it into stack
3923 void ILNativeArrayMarshaler::EmitLoadElementCount(ILCodeStream* pslILEmit)
3925 STANDARD_VM_CONTRACT;
3928 // Determine the element count and load into evaluation stack
3930 CREATE_MARSHALER_CARRAY_OPERANDS mops;
3931 m_pargs->m_pMarshalInfo->GetMops(&mops);
3933 if (mops.multiplier != 0)
3936 // SizeParamIndex arg fix up for LCID
3938 unsigned countParamIdx = mops.countParamIdx;
3939 if (!IsCLRToNative(m_dwMarshalFlags))
3941 int lcidParamIdx = m_pslNDirect->GetLCIDParamIdx();
3943 if (lcidParamIdx >= 0 && (unsigned)lcidParamIdx <= countParamIdx)
3945 // the LCID is injected before the count parameter so the index
3946 // has to be incremented to get the unmanaged parameter number
3952 // Load SizeParamIndex argument
3954 pslILEmit->EmitLDARG(countParamIdx);
3960 // Is the SizeParamIndex points to a by-ref parameter?
3961 CorElementType sizeParamIndexArgType;
3962 if (CheckSizeParamIndexArg(mops, &sizeParamIndexArgType))
3964 // Load the by-ref parameter
3965 switch (sizeParamIndexArgType)
3967 case ELEMENT_TYPE_I1:
3968 pslILEmit->EmitLDIND_I1();
3971 case ELEMENT_TYPE_U1:
3972 pslILEmit->EmitLDIND_U1();
3975 case ELEMENT_TYPE_I2:
3976 pslILEmit->EmitLDIND_I2();
3979 case ELEMENT_TYPE_U2:
3980 pslILEmit->EmitLDIND_U2();
3983 case ELEMENT_TYPE_I4:
3984 pslILEmit->EmitLDIND_I4();
3987 case ELEMENT_TYPE_U4:
3988 pslILEmit->EmitLDIND_U4();
3991 case ELEMENT_TYPE_U8:
3992 case ELEMENT_TYPE_I8:
3993 pslILEmit->EmitLDIND_I8();
3996 case ELEMENT_TYPE_I:
3997 case ELEMENT_TYPE_U:
3998 pslILEmit->EmitLDIND_I();
4002 // Should not go here because we should've thrown exception
4008 pslILEmit->EmitCONV_OVF_I4();
4010 // multiplier * arg + additive
4011 pslILEmit->EmitLDC(mops.multiplier);
4012 pslILEmit->EmitMUL_OVF();
4013 pslILEmit->EmitLDC(mops.additive);
4014 pslILEmit->EmitADD_OVF();
4018 pslILEmit->EmitLDC((int)mops.additive);
4022 void ILNativeArrayMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
4024 STANDARD_VM_CONTRACT;
4026 EmitLoadMngdMarshaler(pslILEmit);
4027 EmitLoadManagedHomeAddr(pslILEmit);
4028 EmitLoadNativeHomeAddr(pslILEmit);
4030 if (IsByref(m_dwMarshalFlags))
4033 // Reset the element count just in case there is an exception thrown in the code emitted by
4034 // EmitLoadElementCount. The best thing we can do here is to avoid a crash.
4036 _ASSERTE(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4037 pslILEmit->EmitLDC(0);
4038 pslILEmit->EmitSTLOC(m_dwSavedSizeArg);
4041 // Dynamically calculate element count using SizeParamIndex argument
4042 EmitLoadElementCount(pslILEmit);
4044 if (IsByref(m_dwMarshalFlags))
4047 // Save the native array size before converting it to managed and load it again
4049 _ASSERTE(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4050 pslILEmit->EmitSTLOC(m_dwSavedSizeArg);
4051 pslILEmit->EmitLDLOC(m_dwSavedSizeArg);
4054 // MngdNativeArrayMarshaler::ConvertSpaceToManaged
4055 pslILEmit->EmitCALL(pslILEmit->GetToken(GetConvertSpaceToManagedMethod()), 4, 0);
4058 void ILNativeArrayMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
4060 STANDARD_VM_CONTRACT;
4062 if (IsByref(m_dwMarshalFlags))
4064 _ASSERTE(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4067 // Save the array size before converting it to native
4069 EmitLoadManagedValue(pslILEmit);
4070 ILCodeLabel *pManagedHomeIsNull = pslILEmit->NewCodeLabel();
4071 pslILEmit->EmitBRFALSE(pManagedHomeIsNull);
4072 EmitLoadManagedValue(pslILEmit);
4073 pslILEmit->EmitLDLEN();
4074 pslILEmit->EmitSTLOC(m_dwSavedSizeArg);
4075 pslILEmit->EmitLabel(pManagedHomeIsNull);
4079 ILMngdMarshaler::EmitConvertSpaceCLRToNative(pslILEmit);
4082 void ILNativeArrayMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
4084 STANDARD_VM_CONTRACT;
4086 EmitLoadMngdMarshaler(pslILEmit);
4087 EmitLoadNativeHomeAddr(pslILEmit);
4088 EmitLoadNativeSize(pslILEmit);
4090 pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeMethod()), 3, 0);
4093 void ILNativeArrayMarshaler::EmitLoadNativeSize(ILCodeStream* pslILEmit)
4095 STANDARD_VM_CONTRACT;
4097 if (IsByref(m_dwMarshalFlags))
4099 _ASSERT(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4100 pslILEmit->EmitLDLOC(m_dwSavedSizeArg);
4104 pslILEmit->EmitLDC(0);
4105 EmitLoadManagedValue(pslILEmit);
4106 ILCodeLabel *pManagedHomeIsNull = pslILEmit->NewCodeLabel();
4107 pslILEmit->EmitBRFALSE(pManagedHomeIsNull);
4108 pslILEmit->EmitPOP(); // Pop the 0 on the stack
4109 EmitLoadManagedValue(pslILEmit);
4110 pslILEmit->EmitLDLEN();
4111 pslILEmit->EmitCONV_OVF_I4();
4112 pslILEmit->EmitLabel(pManagedHomeIsNull); // Keep the 0 on the stack
4116 void ILNativeArrayMarshaler::EmitClearNativeContents(ILCodeStream* pslILEmit)
4118 STANDARD_VM_CONTRACT;
4120 EmitLoadMngdMarshaler(pslILEmit);
4121 EmitLoadNativeHomeAddr(pslILEmit);
4122 EmitLoadNativeSize(pslILEmit);
4124 pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeContentsMethod()), 3, 0);
4127 void ILNativeArrayMarshaler::EmitNewSavedSizeArgLocal()
4129 STANDARD_VM_CONTRACT;
4131 _ASSERTE(m_dwSavedSizeArg == LOCAL_NUM_UNUSED);
4132 ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream();
4133 m_dwSavedSizeArg = pcsSetup->NewLocal(ELEMENT_TYPE_I4);
4134 pcsSetup->EmitLDC(0);
4135 pcsSetup->EmitSTLOC(m_dwSavedSizeArg);
4138 void ILNativeArrayMarshaler::EmitMarshalArgumentNativeToCLRByref()
4140 STANDARD_VM_CONTRACT;
4142 if (IsByref(m_dwMarshalFlags))
4144 EmitNewSavedSizeArgLocal();
4147 ILMngdMarshaler::EmitMarshalArgumentNativeToCLRByref();
4150 void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNativeByref()
4152 STANDARD_VM_CONTRACT;
4154 if (IsByref(m_dwMarshalFlags))
4156 EmitNewSavedSizeArgLocal();
4159 ILMngdMarshaler::EmitMarshalArgumentCLRToNativeByref();
4163 #ifndef CROSSGEN_COMPILE
4165 FCIMPL3(void, MngdNativeArrayMarshaler::CreateMarshaler, MngdNativeArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags)
4169 // Don't check whether the input values are negative - passing negative size-controlling
4170 // arguments and compensating them with a positive SizeConst has always worked.
4171 pThis->m_pElementMT = pMT;
4172 pThis->m_vt = (VARTYPE)(dwFlags);
4173 pThis->m_NativeDataValid = (BYTE)((dwFlags & FLAG_NATIVE_DATA_VALID) != 0);
4174 dwFlags &= ~FLAG_NATIVE_DATA_VALID;
4175 pThis->m_BestFitMap = (BYTE)(dwFlags >> 16);
4176 pThis->m_ThrowOnUnmappableChar = (BYTE)(dwFlags >> 24);
4177 pThis->m_Array = TypeHandle();
4181 FCIMPL3(void, MngdNativeArrayMarshaler::ConvertSpaceToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4185 HELPER_METHOD_FRAME_BEGIN_0();
4187 BASEARRAYREF arrayRef = (BASEARRAYREF) *pManagedHome;
4189 if (arrayRef == NULL)
4191 *pNativeHome = NULL;
4195 SIZE_T cElements = arrayRef->GetNumComponents();
4196 SIZE_T cbElement = OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT);
4199 COMPlusThrow(kArgumentException, IDS_EE_COM_UNSUPPORTED_SIG);
4201 SIZE_T cbArray = cElements;
4202 if ( (!SafeMulSIZE_T(&cbArray, cbElement)) || cbArray > MAX_SIZE_FOR_INTEROP)
4203 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
4205 *pNativeHome = CoTaskMemAlloc(cbArray);
4206 if (*pNativeHome == NULL)
4209 // initialize the array
4210 FillMemory(*pNativeHome, cbArray, 0);
4213 HELPER_METHOD_FRAME_END();
4217 FCIMPL3(void, MngdNativeArrayMarshaler::ConvertContentsToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4221 HELPER_METHOD_FRAME_BEGIN_0();
4223 BASEARRAYREF* pArrayRef = (BASEARRAYREF *) pManagedHome;
4225 if (*pArrayRef != NULL)
4227 const OleVariant::Marshaler* pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, TRUE);
4228 SIZE_T cElements = (*pArrayRef)->GetNumComponents();
4229 if (pMarshaler == NULL || pMarshaler->ComToOleArray == NULL)
4231 if ( (!SafeMulSIZE_T(&cElements, OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT))) || cElements > MAX_SIZE_FOR_INTEROP)
4232 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
4234 _ASSERTE(!GetTypeHandleForCVType(OleVariant::GetCVTypeForVarType(pThis->m_vt)).GetMethodTable()->ContainsPointers());
4235 memcpyNoGCRefs(*pNativeHome, (*pArrayRef)->GetDataPtr(), cElements);
4239 pMarshaler->ComToOleArray(pArrayRef, *pNativeHome, pThis->m_pElementMT, pThis->m_BestFitMap,
4240 pThis->m_ThrowOnUnmappableChar, pThis->m_NativeDataValid, cElements);
4243 HELPER_METHOD_FRAME_END();
4247 FCIMPL4(void, MngdNativeArrayMarshaler::ConvertSpaceToManaged, MngdNativeArrayMarshaler* pThis,
4248 OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements)
4252 HELPER_METHOD_FRAME_BEGIN_0();
4254 if (*pNativeHome == NULL)
4256 SetObjectReference(pManagedHome, NULL, GetAppDomain());
4260 // <TODO>@todo: lookup this class before marshal time</TODO>
4261 if (pThis->m_Array.IsNull())
4263 // Get proper array class name & type
4264 pThis->m_Array = OleVariant::GetArrayForVarType(pThis->m_vt, TypeHandle(pThis->m_pElementMT));
4265 if (pThis->m_Array.IsNull())
4266 COMPlusThrow(kTypeLoadException);
4271 SetObjectReference(pManagedHome, AllocateArrayEx(pThis->m_Array, &cElements, 1), GetAppDomain());
4273 HELPER_METHOD_FRAME_END();
4277 FCIMPL3(void, MngdNativeArrayMarshaler::ConvertContentsToManaged, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4281 HELPER_METHOD_FRAME_BEGIN_0();
4283 if (*pNativeHome != NULL)
4285 const OleVariant::Marshaler *pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, TRUE);
4287 BASEARRAYREF* pArrayRef = (BASEARRAYREF*) pManagedHome;
4289 if (pMarshaler == NULL || pMarshaler->OleToComArray == NULL)
4291 SIZE_T cElements = (*pArrayRef)->GetNumComponents();
4292 if ( (!SafeMulSIZE_T(&cElements, OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT))) || cElements > MAX_SIZE_FOR_INTEROP)
4293 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
4295 // If we are copying variants, strings, etc, we need to use write barrier
4296 _ASSERTE(!GetTypeHandleForCVType(OleVariant::GetCVTypeForVarType(pThis->m_vt)).GetMethodTable()->ContainsPointers());
4297 memcpyNoGCRefs((*pArrayRef)->GetDataPtr(), *pNativeHome, cElements);
4301 pMarshaler->OleToComArray(*pNativeHome, pArrayRef, pThis->m_pElementMT);
4305 HELPER_METHOD_FRAME_END();
4309 FCIMPL3(void, MngdNativeArrayMarshaler::ClearNative, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
4313 HELPER_METHOD_FRAME_BEGIN_0();
4315 if (*pNativeHome != NULL)
4317 DoClearNativeContents(pThis, pNativeHome, cElements);
4318 CoTaskMemFree(*pNativeHome);
4321 HELPER_METHOD_FRAME_END();
4325 FCIMPL3(void, MngdNativeArrayMarshaler::ClearNativeContents, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
4329 HELPER_METHOD_FRAME_BEGIN_0();
4331 DoClearNativeContents(pThis, pNativeHome, cElements);
4333 HELPER_METHOD_FRAME_END();
4337 void MngdNativeArrayMarshaler::DoClearNativeContents(MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
4347 if (*pNativeHome != NULL)
4349 const OleVariant::Marshaler *pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, FALSE);
4351 if (pMarshaler != NULL && pMarshaler->ClearOleArray != NULL)
4353 pMarshaler->ClearOleArray(*pNativeHome, cElements, pThis->m_pElementMT);
4358 #endif // CROSSGEN_COMPILE
4361 #ifdef FEATURE_COMINTEROP
4362 void ILSafeArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
4364 STANDARD_VM_CONTRACT;
4366 m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4368 pslILEmit->EmitLDC(sizeof(MngdSafeArrayMarshaler));
4369 pslILEmit->EmitLOCALLOC();
4370 pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
4372 CREATE_MARSHALER_CARRAY_OPERANDS mops;
4373 m_pargs->m_pMarshalInfo->GetMops(&mops);
4375 DWORD dwFlags = mops.elementType;
4378 if (NeedsCheckForStatic())
4380 fStatic |= MngdSafeArrayMarshaler::SCSF_CheckForStatic;
4383 if (!IsCLRToNative(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
4385 // Unmanaged->managed in/out is the only case where we expect the native buffer to contain valid data.
4386 fStatic |= MngdSafeArrayMarshaler::SCSF_NativeDataValid;
4389 dwFlags |= fStatic << 16;
4390 dwFlags |= ((BYTE)!!m_pargs->m_pMarshalInfo->GetNoLowerBounds()) << 24;
4392 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
4393 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(mops.methodTable));
4394 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
4395 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetArrayRank());
4396 pslILEmit->EmitLDC(dwFlags);
4398 pslILEmit->EmitCALL(METHOD__MNGD_SAFE_ARRAY_MARSHALER__CREATE_MARSHALER, 4, 0);
4401 void ILSafeArrayMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
4403 STANDARD_VM_CONTRACT;
4405 ILMngdMarshaler::EmitConvertContentsNativeToCLR(pslILEmit);
4407 if (NeedsCheckForStatic())
4409 CONSISTENCY_CHECK(-1 == m_dwOriginalManagedLocalNum);
4410 m_dwOriginalManagedLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_OBJECT);
4411 EmitLoadManagedValue(pslILEmit);
4412 pslILEmit->EmitSTLOC(m_dwOriginalManagedLocalNum);
4416 void ILSafeArrayMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
4418 STANDARD_VM_CONTRACT;
4420 EmitLoadMngdMarshaler(pslILEmit);
4421 EmitLoadManagedHomeAddr(pslILEmit);
4422 EmitLoadNativeHomeAddr(pslILEmit);
4423 if (NeedsCheckForStatic())
4425 CONSISTENCY_CHECK(-1 != m_dwOriginalManagedLocalNum);
4426 pslILEmit->EmitLDLOC(m_dwOriginalManagedLocalNum);
4430 pslILEmit->EmitLDNULL();
4432 pslILEmit->EmitCALL(METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE, 4, 0);
4436 #ifndef CROSSGEN_COMPILE
4438 FCIMPL4(void, MngdSafeArrayMarshaler::CreateMarshaler, MngdSafeArrayMarshaler* pThis, MethodTable* pMT, UINT32 iRank, UINT32 dwFlags)
4442 pThis->m_pElementMT = pMT;
4443 pThis->m_iRank = iRank;
4444 pThis->m_vt = (VARTYPE)dwFlags;
4445 pThis->m_fStatic = (BYTE)(dwFlags >> 16);
4446 pThis->m_nolowerbounds = (BYTE)(dwFlags >> 24);
4450 FCIMPL3(void, MngdSafeArrayMarshaler::ConvertSpaceToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4454 if (pThis->m_fStatic & SCSF_IsStatic)
4457 HELPER_METHOD_FRAME_BEGIN_0();
4464 PRECONDITION(pThis->m_vt != VT_EMPTY);
4465 PRECONDITION(CheckPointer(pThis->m_pElementMT));
4469 if (*pManagedHome != NULL)
4471 *pNativeHome = (void *) OleVariant::CreateSafeArrayForArrayRef((BASEARRAYREF*) pManagedHome, pThis->m_vt, pThis->m_pElementMT);
4475 *pNativeHome = NULL;
4478 HELPER_METHOD_FRAME_END();
4482 FCIMPL4(void, MngdSafeArrayMarshaler::ConvertContentsToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, Object* pOriginalManagedUNSAFE)
4487 PRECONDITION(pThis->m_vt != VT_EMPTY);
4488 PRECONDITION(CheckPointer(pThis->m_pElementMT));
4492 OBJECTREF pOriginalManaged = ObjectToOBJECTREF(pOriginalManagedUNSAFE);
4493 HELPER_METHOD_FRAME_BEGIN_1(pOriginalManaged);
4495 if ((pThis->m_fStatic & SCSF_IsStatic) &&
4496 (*pManagedHome != pOriginalManaged))
4498 COMPlusThrow(kInvalidOperationException, IDS_INVALID_REDIM);
4501 if (*pManagedHome != NULL)
4503 OleVariant::MarshalSafeArrayForArrayRef((BASEARRAYREF *) pManagedHome,
4504 (SAFEARRAY*)*pNativeHome,
4506 pThis->m_pElementMT,
4507 (pThis->m_fStatic & SCSF_NativeDataValid));
4510 HELPER_METHOD_FRAME_END();
4514 FCIMPL3(void, MngdSafeArrayMarshaler::ConvertSpaceToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4519 PRECONDITION(pThis->m_vt != VT_EMPTY);
4520 PRECONDITION(CheckPointer(pThis->m_pElementMT));
4524 HELPER_METHOD_FRAME_BEGIN_0();
4526 if (*pNativeHome != NULL)
4528 // If the managed array has a rank defined then make sure the rank of the
4529 // SafeArray matches the defined rank.
4530 if (pThis->m_iRank != -1)
4532 int iSafeArrayRank = SafeArrayGetDim((SAFEARRAY*) *pNativeHome);
4533 if (pThis->m_iRank != iSafeArrayRank)
4535 WCHAR strExpectedRank[64];
4536 WCHAR strActualRank[64];
4537 _ltow_s(pThis->m_iRank, strExpectedRank, COUNTOF(strExpectedRank), 10);
4538 _ltow_s(iSafeArrayRank, strActualRank, COUNTOF(strActualRank), 10);
4539 COMPlusThrow(kSafeArrayRankMismatchException, IDS_EE_SAFEARRAYRANKMISMATCH, strActualRank, strExpectedRank);
4543 if (pThis->m_nolowerbounds)
4546 if ( (SafeArrayGetDim( (SAFEARRAY*)*pNativeHome ) != 1) ||
4547 (FAILED(SafeArrayGetLBound( (SAFEARRAY*)*pNativeHome, 1, &lowerbound))) ||
4550 COMPlusThrow(kSafeArrayRankMismatchException, IDS_EE_SAFEARRAYSZARRAYMISMATCH);
4554 SetObjectReference(pManagedHome,
4555 (OBJECTREF) OleVariant::CreateArrayRefForSafeArray((SAFEARRAY*) *pNativeHome,
4557 pThis->m_pElementMT), GetAppDomain());
4561 SetObjectReference(pManagedHome, NULL, GetAppDomain());
4564 HELPER_METHOD_FRAME_END();
4568 FCIMPL3(void, MngdSafeArrayMarshaler::ConvertContentsToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4573 PRECONDITION(pThis->m_vt != VT_EMPTY);
4574 PRECONDITION(CheckPointer(pThis->m_pElementMT));
4578 SAFEARRAY* pNative = *(SAFEARRAY**)pNativeHome;
4579 HELPER_METHOD_FRAME_BEGIN_0();
4581 if (pNative && pNative->fFeatures & FADF_STATIC)
4583 pThis->m_fStatic |= SCSF_IsStatic;
4586 if (*pNativeHome != NULL)
4588 OleVariant::MarshalArrayRefForSafeArray((SAFEARRAY*)*pNativeHome,
4589 (BASEARRAYREF *) pManagedHome,
4591 pThis->m_pElementMT);
4594 HELPER_METHOD_FRAME_END();
4598 FCIMPL3(void, MngdSafeArrayMarshaler::ClearNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4602 if (pThis->m_fStatic & SCSF_IsStatic)
4605 HELPER_METHOD_FRAME_BEGIN_0();
4607 if (*pNativeHome != NULL)
4610 _ASSERTE(GetModuleHandleA("oleaut32.dll") != NULL);
4611 // SafeArray has been created. Oleaut32.dll must have been loaded.
4612 CONTRACT_VIOLATION(ThrowsViolation);
4613 SafeArrayDestroy((SAFEARRAY*)*pNativeHome);
4616 HELPER_METHOD_FRAME_END();
4620 #endif // CROSSGEN_COMPILE
4623 LocalDesc ILHiddenLengthArrayMarshaler::GetNativeType()
4625 LIMITED_METHOD_CONTRACT;
4626 return LocalDesc(ELEMENT_TYPE_I);
4629 LocalDesc ILHiddenLengthArrayMarshaler::GetManagedType()
4631 LIMITED_METHOD_CONTRACT;
4632 return LocalDesc(ELEMENT_TYPE_OBJECT);
4635 void ILHiddenLengthArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
4637 STANDARD_VM_CONTRACT;
4639 if (!CanUsePinnedArray())
4641 m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4643 pslILEmit->EmitLDC(sizeof(MngdHiddenLengthArrayMarshaler));
4644 pslILEmit->EmitLOCALLOC();
4645 pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
4647 MethodTable *pElementMT = m_pargs->m_pMarshalInfo->GetArrayElementTypeHandle().GetMethodTable();
4648 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
4649 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(pElementMT));
4650 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
4652 pslILEmit->EmitLDC(m_pargs->na.m_cbElementSize);
4653 pslILEmit->EmitLDC(m_pargs->na.m_vt);
4655 pslILEmit->EmitCALL(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CREATE_MARSHALER, 4, 0);
4659 void ILHiddenLengthArrayMarshaler::EmitMarshalArgumentCLRToNative()
4661 STANDARD_VM_CONTRACT;
4663 // If we can pin the array, then do that rather than marshaling it in a more heavy weight way
4664 // Otherwise, fall back to doing a full marshal
4665 if (CanUsePinnedArray())
4667 EmitSetupSigAndDefaultHomesCLRToNative();
4669 LocalDesc managedType = GetManagedType();
4670 managedType.MakePinned();
4671 DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedType);
4673 ILCodeLabel* pMarshalDoneLabel = m_pcsMarshal->NewCodeLabel();
4676 m_pcsMarshal->EmitLoadNullPtr();
4677 EmitStoreNativeValue(m_pcsMarshal);
4679 // if (managed == null) goto MarshalDone
4680 EmitLoadManagedValue(m_pcsMarshal);
4681 m_pcsMarshal->EmitBRFALSE(pMarshalDoneLabel);
4683 // pinnedLocal = managed;
4684 EmitLoadManagedValue(m_pcsMarshal);
4685 m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
4687 // native = pinnedLocal + dataOffset
4688 m_pcsMarshal->EmitLDLOC(dwPinnedLocal);
4689 m_pcsMarshal->EmitCONV_I();
4690 m_pcsMarshal->EmitLDC(m_pargs->na.m_optionalbaseoffset);
4691 m_pcsMarshal->EmitADD();
4692 EmitStoreNativeValue(m_pcsMarshal);
4694 if (g_pConfig->InteropLogArguments())
4696 m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal);
4700 m_pcsMarshal->EmitLabel(pMarshalDoneLabel);
4704 ILMngdMarshaler::EmitMarshalArgumentCLRToNative();
4709 void ILHiddenLengthArrayMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
4711 STANDARD_VM_CONTRACT;
4713 if (!CanUsePinnedArray())
4715 EmitLoadMngdMarshaler(pslILEmit);
4716 EmitLoadManagedHomeAddr(pslILEmit);
4717 EmitLoadNativeHomeAddr(pslILEmit);
4718 EmitLoadNativeArrayLength(pslILEmit);
4720 // MngdHiddenLengthArrayMarshaler::ConvertSpaceToManaged
4721 pslILEmit->EmitCALL(pslILEmit->GetToken(GetConvertSpaceToManagedMethod()), 4, 0);
4725 void ILHiddenLengthArrayMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
4727 STANDARD_VM_CONTRACT;
4729 // If we're marshaling out to native code, then we need to set the length out parameter
4730 if (!IsCLRToNative(m_dwMarshalFlags))
4732 if (IsByref(m_dwMarshalFlags) || IsRetval(m_dwMarshalFlags) || IsOut(m_dwMarshalFlags))
4734 ILCodeLabel *pSkipGetLengthLabel = m_pcsMarshal->NewCodeLabel();
4737 pslILEmit->EmitLDC(0);
4738 pslILEmit->EmitCONV_T(m_pargs->m_pMarshalInfo->GetHiddenLengthParamElementType());
4739 pslILEmit->EmitSTLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
4741 // if (array == null) goto SkipGetLength
4742 EmitLoadManagedValue(pslILEmit);
4743 pslILEmit->EmitBRFALSE(pSkipGetLengthLabel);
4745 // nativeLen = array.Length
4747 EmitLoadManagedValue(pslILEmit);
4748 pslILEmit->EmitLDLEN();
4749 pslILEmit->EmitCONV_T(m_pargs->m_pMarshalInfo->GetHiddenLengthParamElementType());
4750 pslILEmit->EmitSTLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
4751 pslILEmit->EmitLabel(pSkipGetLengthLabel);
4753 // nativeLenParam = nativeLen
4754 LocalDesc nativeParamType(m_pargs->m_pMarshalInfo->GetHiddenLengthParamElementType());
4755 pslILEmit->EmitLDARG(m_pargs->m_pMarshalInfo->HiddenLengthParamIndex());
4756 pslILEmit->EmitLDLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
4757 pslILEmit->EmitSTIND_T(&nativeParamType);
4761 if (!CanUsePinnedArray())
4763 ILMngdMarshaler::EmitConvertSpaceCLRToNative(pslILEmit);
4767 void ILHiddenLengthArrayMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
4769 STANDARD_VM_CONTRACT;
4771 if (!CanUsePinnedArray())
4773 if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE &&
4774 (m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Uri ||
4775 m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs ||
4776 m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs))
4778 // System.Uri/NotifyCollectionChangedEventArgs don't live in mscorlib so there's no marshaling helper to call - inline the loop
4779 DWORD dwLoopCounterLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
4780 DWORD dwNativePtrLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4781 ILCodeLabel *pConditionLabel = pslILEmit->NewCodeLabel();
4782 ILCodeLabel *pLoopBodyLabel = pslILEmit->NewCodeLabel();
4784 // for (IntPtr ptr = pNative, int i = 0; ...
4785 pslILEmit->EmitLDC(0);
4786 pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4787 EmitLoadNativeValue(pslILEmit);
4788 pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4789 pslILEmit->EmitBR(pConditionLabel);
4791 // *ptr = EmitConvertCLR*ToWinRT*(pManaged[i]);
4792 pslILEmit->EmitLabel(pLoopBodyLabel);
4793 pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4794 EmitLoadManagedValue(pslILEmit);
4795 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4796 pslILEmit->EmitLDELEM_REF();
4798 switch (m_pargs->na.m_redirectedTypeIndex)
4800 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
4801 ILUriMarshaler::EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4804 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
4805 ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4808 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
4809 ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4812 default: UNREACHABLE();
4815 pslILEmit->EmitSTIND_I();
4817 // ... i++, ptr += IntPtr.Size ...
4818 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4819 pslILEmit->EmitLDC(1);
4820 pslILEmit->EmitADD();
4821 pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4822 pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4823 pslILEmit->EmitLDC(sizeof(LPVOID));
4824 pslILEmit->EmitADD();
4825 pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4827 // ... i < pManaged.Length; ...
4828 pslILEmit->EmitLabel(pConditionLabel);
4829 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4830 EmitLoadNativeArrayLength(pslILEmit);
4831 pslILEmit->EmitBLT(pLoopBodyLabel);
4835 ILMngdMarshaler::EmitConvertContentsCLRToNative(pslILEmit);
4840 void ILHiddenLengthArrayMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
4842 STANDARD_VM_CONTRACT;
4844 if (!CanUsePinnedArray())
4846 if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE &&
4847 (m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Uri ||
4848 m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs ||
4849 m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs))
4851 // System.Uri/NotifyCollectionChangedEventArgs don't live in mscorlib so there's no marshaling helper to call - inline the loop
4852 DWORD dwLoopCounterLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
4853 DWORD dwNativePtrLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4854 ILCodeLabel *pConditionLabel = pslILEmit->NewCodeLabel();
4855 ILCodeLabel *pLoopBodyLabel = pslILEmit->NewCodeLabel();
4857 // for (IntPtr ptr = pNative, int i = 0; ...
4858 pslILEmit->EmitLDC(0);
4859 pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4860 EmitLoadNativeValue(pslILEmit);
4861 pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4862 pslILEmit->EmitBR(pConditionLabel);
4864 // pManaged[i] = EmitConvertWinRT*ToCLR*(*ptr);
4865 pslILEmit->EmitLabel(pLoopBodyLabel);
4866 EmitLoadManagedValue(pslILEmit);
4867 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4868 pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4869 pslILEmit->EmitLDIND_I();
4871 switch (m_pargs->na.m_redirectedTypeIndex)
4873 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
4874 ILUriMarshaler::EmitConvertWinRTUriToCLRUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4877 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
4878 ILNCCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4881 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
4882 ILPCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4885 default: UNREACHABLE();
4888 pslILEmit->EmitSTELEM_REF();
4890 // ... i++, ptr += IntPtr.Size)
4891 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4892 pslILEmit->EmitLDC(1);
4893 pslILEmit->EmitADD();
4894 pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4895 pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4896 pslILEmit->EmitLDC(sizeof(LPVOID));
4897 pslILEmit->EmitADD();
4898 pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4900 // ... i < pManaged.Length; ...
4901 pslILEmit->EmitLabel(pConditionLabel);
4902 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4903 EmitLoadNativeArrayLength(pslILEmit);
4904 pslILEmit->EmitBLT(pLoopBodyLabel);
4908 ILMngdMarshaler::EmitConvertContentsNativeToCLR(pslILEmit);
4913 void ILHiddenLengthArrayMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
4915 STANDARD_VM_CONTRACT;
4917 EmitClearNativeContents(pslILEmit);
4919 if (!CanUsePinnedArray())
4921 EmitLoadNativeValue(pslILEmit);
4922 pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeMethod()), 1, 0);
4926 void ILHiddenLengthArrayMarshaler::EmitClearNativeContents(ILCodeStream* pslILEmit)
4928 STANDARD_VM_CONTRACT;
4930 if (!CanUsePinnedArray())
4932 MethodDesc *pMD = GetClearNativeContentsMethod();
4936 UINT numArgs = sig.NumFixedArgs();
4940 EmitLoadMngdMarshaler(pslILEmit);
4944 _ASSERTE(numArgs == 2);
4947 EmitLoadNativeHomeAddr(pslILEmit);
4948 EmitLoadNativeArrayLength(pslILEmit);
4949 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), numArgs, 0);
4954 // Determine if we can simply pin the managed array, rather than doing a full marshal
4955 bool ILHiddenLengthArrayMarshaler::CanUsePinnedArray()
4957 STANDARD_VM_CONTRACT;
4959 // If the array is only going from managed to native, and it contains only blittable data, and
4960 // we know where that data is located in the array then we can take the fast path
4961 if (!IsCLRToNative(m_dwMarshalFlags))
4966 if (m_pargs->na.m_vt != VTHACK_BLITTABLERECORD)
4971 if (IsByref(m_dwMarshalFlags))
4976 if (!IsIn(m_dwMarshalFlags))
4981 if (IsRetval(m_dwMarshalFlags))
4986 if (m_pargs->na.m_optionalbaseoffset == 0)
4994 void ILHiddenLengthArrayMarshaler::EmitLoadNativeArrayLength(ILCodeStream *pslILEmit)
4996 STANDARD_VM_CONTRACT;
4998 // For return values, the native length won't yet be marshaled back to its managed home
4999 // so it needs to be read directly
5000 if (IsRetval(m_dwMarshalFlags))
5002 pslILEmit->EmitLDLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
5006 pslILEmit->EmitLDLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthManagedHome());
5009 pslILEmit->EmitCONV_OVF_I4();
5012 MethodDesc *ILHiddenLengthArrayMarshaler::GetConvertContentsToManagedMethod()
5014 STANDARD_VM_CONTRACT;
5016 if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE)
5018 switch (m_pargs->na.m_redirectedTypeIndex)
5020 case WinMDAdapter::RedirectedTypeIndex_System_DateTimeOffset:
5021 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_DATETIME);
5023 case WinMDAdapter::RedirectedTypeIndex_System_Type:
5024 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_TYPE);
5026 case WinMDAdapter::RedirectedTypeIndex_System_Exception:
5027 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_EXCEPTION);
5029 case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
5031 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_NULLABLE);
5032 return GetExactMarshalerMethod(pMD);
5035 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
5037 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_KEYVALUEPAIR);
5038 return GetExactMarshalerMethod(pMD);
5042 UNREACHABLE_MSG("Unrecognized redirected type.");
5045 return ILMngdMarshaler::GetConvertContentsToManagedMethod();
5048 MethodDesc *ILHiddenLengthArrayMarshaler::GetConvertContentsToNativeMethod()
5050 STANDARD_VM_CONTRACT;
5052 if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE)
5054 switch (m_pargs->na.m_redirectedTypeIndex)
5056 case WinMDAdapter::RedirectedTypeIndex_System_DateTimeOffset:
5057 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_DATETIME);
5059 case WinMDAdapter::RedirectedTypeIndex_System_Type:
5060 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_TYPE);
5062 case WinMDAdapter::RedirectedTypeIndex_System_Exception:
5063 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_EXCEPTION);
5065 case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
5067 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_NULLABLE);
5068 return GetExactMarshalerMethod(pMD);
5071 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
5073 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_KEYVALUEPAIR);
5074 return GetExactMarshalerMethod(pMD);
5078 UNREACHABLE_MSG("Unrecognized redirected type.");
5081 return ILMngdMarshaler::GetConvertContentsToNativeMethod();
5084 MethodDesc *ILHiddenLengthArrayMarshaler::GetClearNativeContentsMethod()
5086 switch (m_pargs->na.m_vt)
5088 // HSTRINGs, interface pointers, and non-blittable structs need contents cleanup
5089 case VTHACK_HSTRING:
5090 case VTHACK_INSPECTABLE:
5091 case VTHACK_NONBLITTABLERECORD:
5094 // blittable structs don't need contents cleanup
5095 case VTHACK_BLITTABLERECORD:
5098 case VTHACK_REDIRECTEDTYPE:
5100 switch (m_pargs->na.m_redirectedTypeIndex)
5102 // System.Type, Uri, Nullable, KeyValuePair, NCCEventArgs, and PCEventArgs need cleanup
5103 case WinMDAdapter::RedirectedTypeIndex_System_Type:
5104 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CLEAR_NATIVE_CONTENTS_TYPE);
5106 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
5107 case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
5108 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
5109 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
5110 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
5113 // other redirected types don't
5121 UNREACHABLE_MSG("Unexpected hidden-length array element VT");
5124 return ILMngdMarshaler::GetClearNativeContentsMethod();
5127 MethodDesc *ILHiddenLengthArrayMarshaler::GetExactMarshalerMethod(MethodDesc *pGenericMD)
5129 STANDARD_VM_CONTRACT;
5131 return MethodDesc::FindOrCreateAssociatedMethodDesc(
5133 pGenericMD->GetMethodTable(),
5134 FALSE, // forceBoxedEntryPoint
5135 m_pargs->na.m_pMT->GetInstantiation(), // methodInst
5136 FALSE, // allowInstParam
5137 TRUE); // forceRemotableMethod
5140 #ifndef CROSSGEN_COMPILE
5142 FCIMPL4(void, MngdHiddenLengthArrayMarshaler::CreateMarshaler, MngdHiddenLengthArrayMarshaler* pThis, MethodTable* pMT, SIZE_T cbElementSize, UINT16 vt)
5146 pThis->m_pElementMT = pMT;
5147 pThis->m_cbElementSize = cbElementSize;
5148 pThis->m_vt = (VARTYPE)vt;
5152 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertSpaceToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5156 BASEARRAYREF arrayRef = (BASEARRAYREF) *pManagedHome;
5157 HELPER_METHOD_FRAME_BEGIN_1(arrayRef);
5159 if (arrayRef == NULL)
5161 *pNativeHome = NULL;
5165 SIZE_T cbArray = pThis->GetArraySize(arrayRef->GetNumComponents());
5167 *pNativeHome = CoTaskMemAlloc(cbArray);
5168 if (*pNativeHome == NULL)
5173 // initialize the array
5174 FillMemory(*pNativeHome, cbArray, 0);
5177 HELPER_METHOD_FRAME_END();
5181 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertContentsToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5187 PTRARRAYREF arrayRef;
5188 STRINGREF currentStringRef;
5189 OBJECTREF currentObjectRef;
5192 ZeroMemory(&gc, sizeof(gc));
5193 gc.arrayRef = (PTRARRAYREF)*pManagedHome;
5195 HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
5197 if (gc.arrayRef != NULL)
5199 // There are these choices:
5200 // * the array is made up of entirely blittable data, in which case we can directly copy it,
5201 // * it is an array of strings that need to be marshaled as HSTRING,
5202 // * it is an array of non-blittable structures
5203 // * it is an array of interface pointers (interface, runtime class, delegate, System.Object)
5204 switch (pThis->m_vt)
5206 case VTHACK_BLITTABLERECORD:
5208 // Just do a raw memcpy into the array
5209 SIZE_T cbArray = pThis->GetArraySize(gc.arrayRef->GetNumComponents());
5210 memcpyNoGCRefs(*pNativeHome, gc.arrayRef->GetDataPtr(), cbArray);
5214 case VTHACK_HSTRING:
5216 // Marshal a string array as an array of HSTRINGs
5217 if (!WinRTSupported())
5219 COMPlusThrow(kPlatformNotSupportedException, W("PlatformNotSupported_WinRT"));
5222 HSTRING *pDestinationStrings = reinterpret_cast<HSTRING *>(*pNativeHome);
5224 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5226 gc.currentStringRef = (STRINGREF)gc.arrayRef->GetAt(i);
5227 if (gc.currentStringRef == NULL)
5229 StackSString ssIndex;
5230 ssIndex.Printf(W("%d"), i);
5231 COMPlusThrow(kMarshalDirectiveException, IDS_EE_BADMARSHALARRAY_NULL_HSTRING, ssIndex.GetUnicode());
5234 IfFailThrow(WindowsCreateString(gc.currentStringRef->GetBuffer(), gc.currentStringRef->GetStringLength(), &(pDestinationStrings[i])));
5239 case VTHACK_NONBLITTABLERECORD:
5241 BYTE *pNativeStart = reinterpret_cast<BYTE *>(*pNativeHome);
5242 SIZE_T managedOffset = ArrayBase::GetDataPtrOffset(gc.arrayRef->GetMethodTable());
5243 SIZE_T nativeOffset = 0;
5244 SIZE_T managedSize = gc.arrayRef->GetComponentSize();
5245 SIZE_T nativeSize = pThis->m_pElementMT->GetNativeSize();
5246 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5248 LayoutUpdateNative(reinterpret_cast<LPVOID *>(&gc.arrayRef), managedOffset, pThis->m_pElementMT, pNativeStart + nativeOffset, NULL);
5249 managedOffset += managedSize;
5250 nativeOffset += nativeSize;
5255 case VTHACK_INSPECTABLE:
5257 // interface pointers
5258 IUnknown **pDestinationIPs = reinterpret_cast<IUnknown **>(*pNativeHome);
5260 // If this turns out to be a perf issue, we can precompute the ItfMarshalInfo
5261 // and generate code that passes it to the marshaler at creation time.
5262 ItfMarshalInfo itfInfo;
5263 MarshalInfo::GetItfMarshalInfo(TypeHandle(pThis->m_pElementMT), TypeHandle(), FALSE, TRUE, MarshalInfo::MARSHAL_SCENARIO_WINRT, &itfInfo);
5265 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5267 gc.currentObjectRef = gc.arrayRef->GetAt(i);
5268 pDestinationIPs[i] = MarshalObjectToInterface(
5269 &gc.currentObjectRef,
5270 itfInfo.thNativeItf.GetMethodTable(),
5271 itfInfo.thClass.GetMethodTable(),
5278 UNREACHABLE_MSG("Unrecognized array element VARTYPE");
5282 HELPER_METHOD_FRAME_END();
5286 FCIMPL4(void, MngdHiddenLengthArrayMarshaler::ConvertSpaceToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements)
5290 HELPER_METHOD_FRAME_BEGIN_0();
5292 if (*pNativeHome == NULL)
5294 SetObjectReference(pManagedHome, NULL, GetAppDomain());
5298 TypeHandle elementType(pThis->m_pElementMT);
5299 TypeHandle arrayType = ClassLoader::LoadArrayTypeThrowing(elementType);
5300 SetObjectReference(pManagedHome, AllocateArrayEx(arrayType, &cElements, 1), GetAppDomain());
5303 HELPER_METHOD_FRAME_END();
5307 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertContentsToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5313 PTRARRAYREF arrayRef;
5314 STRINGREF stringRef;
5315 OBJECTREF objectRef;
5318 ZeroMemory(&gc, sizeof(gc));
5319 gc.arrayRef = (PTRARRAYREF)*pManagedHome;
5321 HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
5323 if (*pNativeHome != NULL)
5325 // There are these choices:
5326 // * the array is made up of entirely blittable data, in which case we can directly copy it,
5327 // * it is an array of strings that need to be marshaled as HSTRING,
5328 // * it is an array of non-blittable structures
5329 // * it is an array of interface pointers (interface, runtime class, delegate, System.Object)
5330 switch (pThis->m_vt)
5332 case VTHACK_BLITTABLERECORD:
5334 // Just do a raw memcpy into the array
5335 SIZE_T cbArray = pThis->GetArraySize(gc.arrayRef->GetNumComponents());
5336 memcpyNoGCRefs(gc.arrayRef->GetDataPtr(), *pNativeHome, cbArray);
5340 case VTHACK_HSTRING:
5342 // Strings are in HSRING format on the native side
5343 if (!WinRTSupported())
5345 COMPlusThrow(kPlatformNotSupportedException, W("PlatformNotSupported_WinRT"));
5348 HSTRING *pSourceStrings = reinterpret_cast<HSTRING *>(*pNativeHome);
5350 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5352 // NULL HSTRINGS are equivilent to empty strings
5353 UINT32 cchString = 0;
5354 LPCWSTR pwszString = W("");
5356 if (pSourceStrings[i] != NULL)
5358 pwszString = WindowsGetStringRawBuffer(pSourceStrings[i], &cchString);
5361 gc.stringRef = StringObject::NewString(pwszString, cchString);
5362 gc.arrayRef->SetAt(i, gc.stringRef);
5367 case VTHACK_NONBLITTABLERECORD:
5369 // Defer to the field marshaler to handle structures
5370 BYTE *pNativeStart = reinterpret_cast<BYTE *>(*pNativeHome);
5371 SIZE_T managedOffset = ArrayBase::GetDataPtrOffset(gc.arrayRef->GetMethodTable());
5372 SIZE_T nativeOffset = 0;
5373 SIZE_T managedSize = gc.arrayRef->GetComponentSize();
5374 SIZE_T nativeSize = pThis->m_pElementMT->GetNativeSize();
5375 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5377 LayoutUpdateCLR(reinterpret_cast<LPVOID *>(&gc.arrayRef), managedOffset, pThis->m_pElementMT, pNativeStart + nativeOffset);
5378 managedOffset += managedSize;
5379 nativeOffset += nativeSize;
5384 case VTHACK_INSPECTABLE:
5386 // interface pointers
5387 IUnknown **pSourceIPs = reinterpret_cast<IUnknown **>(*pNativeHome);
5389 // If this turns out to be a perf issue, we can precompute the ItfMarshalInfo
5390 // and generate code that passes it to the marshaler at creation time.
5391 ItfMarshalInfo itfInfo;
5392 MarshalInfo::GetItfMarshalInfo(TypeHandle(pThis->m_pElementMT), TypeHandle(), FALSE, TRUE, MarshalInfo::MARSHAL_SCENARIO_WINRT, &itfInfo);
5394 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5396 gc.objectRef = gc.arrayRef->GetAt(i);
5397 UnmarshalObjectFromInterface(
5400 itfInfo.thItf.GetMethodTable(),
5401 itfInfo.thClass.GetMethodTable(),
5403 gc.arrayRef->SetAt(i, gc.objectRef);
5409 UNREACHABLE_MSG("Unrecognized array element VARTYPE");
5413 HELPER_METHOD_FRAME_END();
5417 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ClearNativeContents, MngdHiddenLengthArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
5421 HELPER_METHOD_FRAME_BEGIN_0();
5423 if (*pNativeHome != NULL)
5425 pThis->DoClearNativeContents(pNativeHome, cElements);
5428 HELPER_METHOD_FRAME_END();
5432 #endif // CROSSGEN_COMPILE
5435 SIZE_T MngdHiddenLengthArrayMarshaler::GetArraySize(SIZE_T elements)
5445 _ASSERTE_MSG(m_cbElementSize != 0, "You have to set the native size for your array element type");
5449 if (!ClrSafeInt<SIZE_T>::multiply(elements, m_cbElementSize, cbArray))
5451 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
5454 // This array size limit is carried over from the equivilent limit for other array marshaling code
5455 if (cbArray > MAX_SIZE_FOR_INTEROP)
5457 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
5463 #ifndef CROSSGEN_COMPILE
5464 void MngdHiddenLengthArrayMarshaler::DoClearNativeContents(void** pNativeHome, INT32 cElements)
5471 PRECONDITION(pNativeHome != NULL);
5476 if (vt == VTHACK_REDIRECTEDTYPE)
5478 // the redirected types that use this helper are interface pointers on the WinRT side
5479 vt = VTHACK_INSPECTABLE;
5484 case VTHACK_HSTRING:
5486 if (WinRTSupported())
5488 HSTRING *pStrings = reinterpret_cast<HSTRING *>(*pNativeHome);
5489 for (INT32 i = 0; i < cElements; ++i)
5491 if (pStrings[i] != NULL)
5493 WindowsDeleteString(pStrings[i]);
5500 case VTHACK_NONBLITTABLERECORD:
5502 SIZE_T cbArray = GetArraySize(cElements);
5503 BYTE *pNativeCurrent = reinterpret_cast<BYTE *>(*pNativeHome);
5504 BYTE *pNativeEnd = pNativeCurrent + cbArray;
5506 while (pNativeCurrent < pNativeEnd)
5508 LayoutDestroyNative(pNativeCurrent, m_pElementMT);
5509 pNativeCurrent += m_pElementMT->GetNativeSize();
5514 case VTHACK_INSPECTABLE:
5516 IInspectable **pIPs = reinterpret_cast<IInspectable **>(*pNativeHome);
5517 for (INT32 i = 0; i < cElements; ++i)
5519 if (pIPs[i] != NULL)
5521 SafeRelease(pIPs[i]);
5528 UNREACHABLE_MSG("Unexpected hidden-length array element VT");
5531 #endif //CROSSGEN_COMPILE
5532 #endif // FEATURE_COMINTEROP
5534 void ILReferenceCustomMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
5539 PRECONDITION(-1 == m_dwMngdMarshalerLocalNum);
5544 // allocate space for marshaler
5547 m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
5549 pslILEmit->EmitLDC(sizeof(MngdRefCustomMarshaler));
5550 pslILEmit->EmitLOCALLOC();
5551 pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
5553 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum); // arg to CreateMarshaler
5556 // call CreateCustomMarshalerHelper
5559 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(m_pargs->rcm.m_pMD));
5560 pslILEmit->EmitCALL(METHOD__METHOD_HANDLE__GETVALUEINTERNAL, 1, 1);
5562 pslILEmit->EmitLDC(m_pargs->rcm.m_paramToken);
5564 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(TypeHandle::FromPtr(m_pargs->rcm.m_hndManagedType)));
5565 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
5567 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CREATE_CUSTOM_MARSHALER_HELPER, 3, 1); // arg to CreateMarshaler
5570 // call MngdRefCustomMarshaler::CreateMarshaler
5573 pslILEmit->EmitCALL(METHOD__MNGD_REF_CUSTOM_MARSHALER__CREATE_MARSHALER, 2, 0);
5577 #ifndef CROSSGEN_COMPILE
5579 FCIMPL2(void, MngdRefCustomMarshaler::CreateMarshaler, MngdRefCustomMarshaler* pThis, void* pCMHelper)
5583 pThis->m_pCMHelper = (CustomMarshalerHelper*)pCMHelper;
5588 FCIMPL3(void, MngdRefCustomMarshaler::ConvertContentsToNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5593 PRECONDITION(CheckPointer(pManagedHome));
5597 HELPER_METHOD_FRAME_BEGIN_0();
5599 *pNativeHome = pThis->m_pCMHelper->InvokeMarshalManagedToNativeMeth(*pManagedHome);
5601 HELPER_METHOD_FRAME_END();
5606 FCIMPL3(void, MngdRefCustomMarshaler::ConvertContentsToManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5611 PRECONDITION(CheckPointer(pManagedHome));
5615 HELPER_METHOD_FRAME_BEGIN_0();
5617 SetObjectReference(pManagedHome, pThis->m_pCMHelper->InvokeMarshalNativeToManagedMeth(*pNativeHome), GetAppDomain());
5619 HELPER_METHOD_FRAME_END();
5623 FCIMPL3(void, MngdRefCustomMarshaler::ClearNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5627 HELPER_METHOD_FRAME_BEGIN_0();
5637 pThis->m_pCMHelper->InvokeCleanUpNativeMeth(*pNativeHome);
5639 HELPER_METHOD_FRAME_END();
5643 FCIMPL3(void, MngdRefCustomMarshaler::ClearManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5648 PRECONDITION(CheckPointer(pManagedHome));
5652 HELPER_METHOD_FRAME_BEGIN_0();
5654 pThis->m_pCMHelper->InvokeCleanUpManagedMeth(*pManagedHome);
5656 HELPER_METHOD_FRAME_END();
5660 #endif // CROSSGEN_COMPILE
5663 #ifdef FEATURE_COMINTEROP
5665 ///////////////////////////////////////////////////////////////////////////////////////////////////
5666 // ILUriMarshaler implementation
5667 ///////////////////////////////////////////////////////////////////////////////////////////////////
5669 LocalDesc ILUriMarshaler::GetNativeType()
5671 LIMITED_METHOD_CONTRACT;
5672 return LocalDesc(ELEMENT_TYPE_I);
5675 LocalDesc ILUriMarshaler::GetManagedType()
5677 STANDARD_VM_CONTRACT;;
5678 BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
5679 TypeHandle hndUriType = pDomain->GetMarshalingData()->GetUriMarshalingInfo()->GetSystemUriType();
5681 return LocalDesc(hndUriType); // System.Uri
5684 bool ILUriMarshaler::NeedsClearNative()
5686 LIMITED_METHOD_CONTRACT;
5690 // Note that this method expects the CLR Uri on top of the evaluation stack and leaves the WinRT Uri there.
5692 void ILUriMarshaler::EmitConvertCLRUriToWinRTUri(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5694 STANDARD_VM_CONTRACT;
5696 UriMarshalingInfo* marshalingInfo = pDomain->GetMarshalingData()->GetUriMarshalingInfo();
5698 ILCodeLabel *pNotNullLabel = pslILEmit->NewCodeLabel();
5699 ILCodeLabel *pDoneLabel = pslILEmit->NewCodeLabel();
5701 pslILEmit->EmitDUP();
5702 pslILEmit->EmitBRTRUE(pNotNullLabel);
5704 pslILEmit->EmitPOP();
5705 pslILEmit->EmitLoadNullPtr();
5706 pslILEmit->EmitBR(pDoneLabel);
5708 pslILEmit->EmitLabel(pNotNullLabel);
5710 // System.Uri.get_OriginalString()
5711 MethodDesc* pSystemUriOriginalStringMD = marshalingInfo->GetSystemUriOriginalStringMD();
5712 pslILEmit->EmitCALL(pslILEmit->GetToken(pSystemUriOriginalStringMD), 1, 1);
5714 pslILEmit->EmitCALL(METHOD__URIMARSHALER__CREATE_NATIVE_URI_INSTANCE, 1, 1);
5716 pslILEmit->EmitLabel(pDoneLabel);
5719 void ILUriMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
5721 STANDARD_VM_CONTRACT;
5723 EmitLoadManagedValue(pslILEmit);
5724 EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5725 EmitStoreNativeValue(pslILEmit);
5728 // Note that this method expects the WinRT Uri on top of the evaluation stack and leaves the CLR Uri there.
5730 void ILUriMarshaler::EmitConvertWinRTUriToCLRUri(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5732 STANDARD_VM_CONTRACT;
5734 MethodDesc* pSystemUriCtorMD = pDomain->GetMarshalingData()->GetUriMarshalingInfo()->GetSystemUriCtorMD();
5736 ILCodeLabel *pNotNullLabel = pslILEmit->NewCodeLabel();
5737 ILCodeLabel *pDoneLabel = pslILEmit->NewCodeLabel();
5739 pslILEmit->EmitDUP();
5740 pslILEmit->EmitBRTRUE(pNotNullLabel);
5742 pslILEmit->EmitPOP();
5743 pslILEmit->EmitLDNULL();
5744 pslILEmit->EmitBR(pDoneLabel);
5746 pslILEmit->EmitLabel(pNotNullLabel);
5748 // string UriMarshaler.GetRawUriFromNative(IntPtr)
5749 pslILEmit->EmitCALL(METHOD__URIMARSHALER__GET_RAWURI_FROM_NATIVE, 1, 1);
5751 // System.Uri..ctor(string)
5752 pslILEmit->EmitNEWOBJ(pslILEmit->GetToken(pSystemUriCtorMD), 1);
5754 pslILEmit->EmitLabel(pDoneLabel);
5757 void ILUriMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5759 STANDARD_VM_CONTRACT;
5761 EmitLoadNativeValue(pslILEmit);
5762 EmitConvertWinRTUriToCLRUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5763 EmitStoreManagedValue(pslILEmit);
5766 void ILUriMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
5768 STANDARD_VM_CONTRACT;
5769 EmitInterfaceClearNative(pslILEmit);
5772 ///////////////////////////////////////////////////////////////////////////////////////////////////
5773 // ILNCCEventArgsMarshaler implementation
5774 ///////////////////////////////////////////////////////////////////////////////////////////////////
5776 LocalDesc ILNCCEventArgsMarshaler::GetNativeType()
5778 LIMITED_METHOD_CONTRACT;
5779 return LocalDesc(ELEMENT_TYPE_I);
5782 LocalDesc ILNCCEventArgsMarshaler::GetManagedType()
5784 STANDARD_VM_CONTRACT;;
5786 BaseDomain *pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
5787 TypeHandle hndNCCEventArgType = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemNCCEventArgsType();
5789 return LocalDesc(hndNCCEventArgType); // System.Collections.Specialized.NotifyCollectionChangedEventArgs
5792 bool ILNCCEventArgsMarshaler::NeedsClearNative()
5794 LIMITED_METHOD_CONTRACT;
5798 // Note that this method expects the CLR NotifyCollectionChangedEventArgs on top of the evaluation stack and
5799 // leaves the WinRT NotifyCollectionChangedEventArgs IP there.
5801 void ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream *pslILEmit, BaseDomain *pDomain)
5803 STANDARD_VM_CONTRACT;
5805 MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemNCCEventArgsToWinRTNCCEventArgsMD();
5807 // IntPtr System.Runtime.InteropServices.WindowsRuntime.NotifyCollectionChangedEventArgsMarshaler.ConvertToNative(NotifyCollectionChangedEventArgs)
5808 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5811 void ILNCCEventArgsMarshaler::EmitConvertContentsCLRToNative(ILCodeStream *pslILEmit)
5813 STANDARD_VM_CONTRACT;
5815 EmitLoadManagedValue(pslILEmit);
5816 EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5817 EmitStoreNativeValue(pslILEmit);
5820 // Note that this method expects the WinRT NotifyCollectionChangedEventArgs on top of the evaluation stack and
5821 // leaves the CLR NotifyCollectionChangedEventArgs there.
5823 void ILNCCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5825 STANDARD_VM_CONTRACT;
5827 MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetWinRTNCCEventArgsToSystemNCCEventArgsMD();
5829 // NotifyCollectionChangedEventArgs System.Runtime.InteropServices.WindowsRuntime.NotifyCollectionChangedEventArgsMarshaler.ConvertToManaged(IntPtr)
5830 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5833 void ILNCCEventArgsMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5835 STANDARD_VM_CONTRACT;
5837 EmitLoadNativeValue(pslILEmit);
5838 EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5839 EmitStoreManagedValue(pslILEmit);
5842 void ILNCCEventArgsMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
5844 STANDARD_VM_CONTRACT;
5845 EmitInterfaceClearNative(pslILEmit);
5848 ///////////////////////////////////////////////////////////////////////////////////////////////////
5849 // ILPCEventArgsMarshaler implementation
5850 ///////////////////////////////////////////////////////////////////////////////////////////////////
5852 LocalDesc ILPCEventArgsMarshaler::GetNativeType()
5854 LIMITED_METHOD_CONTRACT;
5855 return LocalDesc(ELEMENT_TYPE_I);
5858 LocalDesc ILPCEventArgsMarshaler::GetManagedType()
5860 STANDARD_VM_CONTRACT;;
5862 BaseDomain *pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
5863 TypeHandle hndPCEventArgType = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemPCEventArgsType();
5865 return LocalDesc(hndPCEventArgType); // System.ComponentModel.PropertyChangedEventArgs
5868 bool ILPCEventArgsMarshaler::NeedsClearNative()
5870 LIMITED_METHOD_CONTRACT;
5874 // Note that this method expects the CLR PropertyChangedEventArgs on top of the evaluation stack and
5875 // leaves the WinRT PropertyChangedEventArgs IP there.
5877 void ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream *pslILEmit, BaseDomain *pDomain)
5879 STANDARD_VM_CONTRACT;
5881 MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemPCEventArgsToWinRTPCEventArgsMD();
5883 // IntPtr System.Runtime.InteropServices.WindowsRuntime.PropertyChangedEventArgsMarshaler.ConvertToNative(PropertyChangedEventArgs)
5884 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5887 void ILPCEventArgsMarshaler::EmitConvertContentsCLRToNative(ILCodeStream *pslILEmit)
5889 STANDARD_VM_CONTRACT;
5891 EmitLoadManagedValue(pslILEmit);
5892 EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5893 EmitStoreNativeValue(pslILEmit);
5896 // Note that this method expects the WinRT PropertyChangedEventArgs on top of the evaluation stack and
5897 // leaves the CLR PropertyChangedEventArgs there.
5899 void ILPCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5901 STANDARD_VM_CONTRACT;
5903 MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetWinRTPCEventArgsToSystemPCEventArgsMD();
5905 // PropertyChangedEventArgs System.Runtime.InteropServices.WindowsRuntime.PropertyChangedEventArgsMarshaler.ConvertToManaged(IntPtr)
5906 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5909 void ILPCEventArgsMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5911 STANDARD_VM_CONTRACT;
5913 EmitLoadNativeValue(pslILEmit);
5914 EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5915 EmitStoreManagedValue(pslILEmit);
5918 void ILPCEventArgsMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
5920 STANDARD_VM_CONTRACT;
5921 EmitInterfaceClearNative(pslILEmit);
5924 ///////////////////////////////////////////////////////////////////////////////////////////////////
5925 // ILDateTimeMarshaler implementation
5926 ///////////////////////////////////////////////////////////////////////////////////////////////////
5928 LocalDesc ILDateTimeMarshaler::GetNativeType()
5930 STANDARD_VM_CONTRACT;;
5931 return LocalDesc(MscorlibBinder::GetClass(CLASS__DATETIMENATIVE));
5934 LocalDesc ILDateTimeMarshaler::GetManagedType()
5936 STANDARD_VM_CONTRACT;;
5937 return LocalDesc(MscorlibBinder::GetClass(CLASS__DATE_TIME_OFFSET));
5940 bool ILDateTimeMarshaler::NeedsClearNative()
5942 LIMITED_METHOD_CONTRACT;
5946 void ILDateTimeMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
5951 PRECONDITION(CheckPointer(pslILEmit));
5955 // DateTimeOffsetMarshaler.ConvertManagedToNative(ref managedDTO, out nativeTicks);
5956 EmitLoadManagedHomeAddr(pslILEmit);
5957 EmitLoadNativeHomeAddr(pslILEmit);
5958 pslILEmit->EmitCALL(METHOD__DATETIMEOFFSETMARSHALER__CONVERT_TO_NATIVE, 2, 0);
5961 void ILDateTimeMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5963 STANDARD_VM_CONTRACT;
5965 // DateTimeOffsetMarshaler.ConvertNativeToManaged(out managedLocalDTO, ref nativeTicks);
5966 EmitLoadManagedHomeAddr(pslILEmit);
5967 EmitLoadNativeHomeAddr(pslILEmit);
5968 pslILEmit->EmitCALL(METHOD__DATETIMEOFFSETMARSHALER__CONVERT_TO_MANAGED, 2, 0);
5971 void ILDateTimeMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
5973 STANDARD_VM_CONTRACT;
5975 EmitLoadNativeHomeAddr(pslILEmit);
5976 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__DATETIMENATIVE)));
5979 ///////////////////////////////////////////////////////////////////////////////////////////////////
5980 // ILNullableMarshaler implementation
5981 ///////////////////////////////////////////////////////////////////////////////////////////////////
5983 LocalDesc ILNullableMarshaler::GetNativeType()
5985 LIMITED_METHOD_CONTRACT;
5986 return LocalDesc(ELEMENT_TYPE_I);
5989 LocalDesc ILNullableMarshaler::GetManagedType()
5991 LIMITED_METHOD_CONTRACT;;
5992 return LocalDesc(m_pargs->m_pMT);
5995 bool ILNullableMarshaler::NeedsClearNative()
5997 LIMITED_METHOD_CONTRACT;
6001 void ILNullableMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
6006 PRECONDITION(CheckPointer(pslILEmit));
6010 // pNative = NullableMarshaler<T>.ConvertToNative(ref pManaged);
6011 EmitLoadManagedHomeAddr(pslILEmit);
6013 MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__NULLABLEMARSHALER__CONVERT_TO_NATIVE));
6014 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6016 EmitStoreNativeValue(pslILEmit);
6019 void ILNullableMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
6021 STANDARD_VM_CONTRACT;
6023 // pManaged = NullableMarshaler.ConvertToManaged(pNative);
6024 EmitLoadNativeValue(pslILEmit);
6026 MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__NULLABLEMARSHALER__CONVERT_TO_MANAGED));
6027 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6029 EmitStoreManagedValue(pslILEmit);
6032 void ILNullableMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
6034 STANDARD_VM_CONTRACT;
6035 EmitInterfaceClearNative(pslILEmit);
6038 MethodDesc *ILNullableMarshaler::GetExactMarshalerMethod(MethodDesc *pGenericMD)
6040 STANDARD_VM_CONTRACT;
6042 return MethodDesc::FindOrCreateAssociatedMethodDesc(
6044 pGenericMD->GetMethodTable(),
6045 FALSE, // forceBoxedEntryPoint
6046 m_pargs->m_pMT->GetInstantiation(), // methodInst
6047 FALSE, // allowInstParam
6048 TRUE); // forceRemotableMethod
6051 ///////////////////////////////////////////////////////////////////////////////////////////////////
6052 // ILSystemTypeMarshaler implementation
6053 ///////////////////////////////////////////////////////////////////////////////////////////////////
6055 LocalDesc ILSystemTypeMarshaler::GetNativeType()
6057 STANDARD_VM_CONTRACT;
6059 return LocalDesc(MscorlibBinder::GetClass(CLASS__TYPENAMENATIVE));
6062 LocalDesc ILSystemTypeMarshaler::GetManagedType()
6064 STANDARD_VM_CONTRACT;
6066 return LocalDesc(MscorlibBinder::GetClass(CLASS__TYPE));
6069 bool ILSystemTypeMarshaler::NeedsClearNative()
6071 LIMITED_METHOD_CONTRACT;
6075 void ILSystemTypeMarshaler::EmitConvertContentsCLRToNative(ILCodeStream * pslILEmit)
6077 STANDARD_VM_CONTRACT;
6079 // SystemTypeMarshaler.ConvertToNative(Type, pTypeName);
6080 EmitLoadManagedValue(pslILEmit);
6081 EmitLoadNativeHomeAddr(pslILEmit);
6082 pslILEmit->EmitCALL(METHOD__SYSTEMTYPEMARSHALER__CONVERT_TO_NATIVE, 2, 0);
6085 void ILSystemTypeMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream * pslILEmit)
6087 STANDARD_VM_CONTRACT;
6089 // type = SystemTypeMarshaler.ConvertNativeToManaged(pTypeName, ref Type);
6090 EmitLoadNativeHomeAddr(pslILEmit);
6091 EmitLoadManagedHomeAddr(pslILEmit);
6092 pslILEmit->EmitCALL(METHOD__SYSTEMTYPEMARSHALER__CONVERT_TO_MANAGED, 2, 0);
6096 void ILSystemTypeMarshaler::EmitClearNative(ILCodeStream * pslILEmit)
6098 STANDARD_VM_CONTRACT;
6100 // SystemTypeMarshaler.ClearNative(pTypeName)
6101 EmitLoadNativeHomeAddr(pslILEmit);
6102 pslILEmit->EmitCALL(METHOD__SYSTEMTYPEMARSHALER__CLEAR_NATIVE, 1, 0);
6105 void ILSystemTypeMarshaler::EmitReInitNative(ILCodeStream * pslILEmit)
6107 EmitLoadNativeHomeAddr(pslILEmit);
6108 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__TYPENAMENATIVE)));
6111 ///////////////////////////////////////////////////////////////////////////////////////////////////
6112 // ILHResultExceptionMarshaler implementation
6113 ///////////////////////////////////////////////////////////////////////////////////////////////////
6115 LocalDesc ILHResultExceptionMarshaler::GetNativeType()
6117 LIMITED_METHOD_CONTRACT;
6118 return LocalDesc(ELEMENT_TYPE_I4);
6121 LocalDesc ILHResultExceptionMarshaler::GetManagedType()
6123 LIMITED_METHOD_CONTRACT;
6124 _ASSERTE(m_pargs->m_pMT != NULL);
6125 return LocalDesc(m_pargs->m_pMT);
6128 bool ILHResultExceptionMarshaler::NeedsClearNative()
6130 LIMITED_METHOD_CONTRACT;
6134 void ILHResultExceptionMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
6139 PRECONDITION(CheckPointer(pslILEmit));
6143 // int HResultExceptionMarshaler.ConvertManagedToNative(Exception);
6144 EmitLoadManagedValue(pslILEmit);
6145 pslILEmit->EmitCALL(METHOD__HRESULTEXCEPTIONMARSHALER__CONVERT_TO_NATIVE, 1, 1);
6146 EmitStoreNativeValue(pslILEmit);
6149 void ILHResultExceptionMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
6154 PRECONDITION(CheckPointer(pslILEmit));
6158 // Exception HResultExceptionMarshaler.ConvertNativeToManaged(int hr);
6159 EmitLoadNativeValue(pslILEmit);
6160 pslILEmit->EmitCALL(METHOD__HRESULTEXCEPTIONMARSHALER__CONVERT_TO_MANAGED, 1, 1);
6161 EmitStoreManagedValue(pslILEmit);
6164 ///////////////////////////////////////////////////////////////////////////////////////////////////
6165 // ILKeyValuePairMarshaler implementation
6166 ///////////////////////////////////////////////////////////////////////////////////////////////////
6168 LocalDesc ILKeyValuePairMarshaler::GetNativeType()
6170 LIMITED_METHOD_CONTRACT;
6171 return LocalDesc(ELEMENT_TYPE_I);
6174 LocalDesc ILKeyValuePairMarshaler::GetManagedType()
6176 LIMITED_METHOD_CONTRACT;;
6177 return LocalDesc(m_pargs->m_pMT);
6180 bool ILKeyValuePairMarshaler::NeedsClearNative()
6182 LIMITED_METHOD_CONTRACT;
6186 void ILKeyValuePairMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
6188 STANDARD_VM_CONTRACT;
6190 // Native = KeyValueMarshaler<K, V>.ConvertToNative([In] ref Managed);
6191 EmitLoadManagedHomeAddr(pslILEmit);
6193 MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__KEYVALUEPAIRMARSHALER__CONVERT_TO_NATIVE));
6194 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6196 EmitStoreNativeValue(pslILEmit);
6199 void ILKeyValuePairMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
6201 STANDARD_VM_CONTRACT;
6203 // Managed = KeyValuePairMarshaler<K, V>.ConvertToManaged(Native);
6204 EmitLoadNativeValue(pslILEmit);
6206 MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__KEYVALUEPAIRMARSHALER__CONVERT_TO_MANAGED));
6207 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6209 EmitStoreManagedValue(pslILEmit);
6212 void ILKeyValuePairMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
6214 STANDARD_VM_CONTRACT;
6215 EmitInterfaceClearNative(pslILEmit);
6218 MethodDesc *ILKeyValuePairMarshaler::GetExactMarshalerMethod(MethodDesc *pGenericMD)
6220 STANDARD_VM_CONTRACT;
6222 // KeyValuePairMarshaler methods are generic - find/create the exact method.
6223 return MethodDesc::FindOrCreateAssociatedMethodDesc(
6225 pGenericMD->GetMethodTable(),
6226 FALSE, // forceBoxedEntryPoint
6227 m_pargs->m_pMT->GetInstantiation(), // methodInst
6228 FALSE, // allowInstParam
6229 TRUE); // forceRemotableMethod
6232 #endif // FEATURE_COMINTEROP