Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/src/dlls/mscorrc/mscorrc.rc
Original file line numberDiff line numberDiff line change
Expand Up@@ -627,7 +627,7 @@ BEGIN
IDS_EE_BADMARSHAL_NOTMARSHALABLE "The type definition of this field has layout information but has an invalid managed/unmanaged type combination or is unmarshalable."
IDS_EE_BADMARSHAL_BADMETADATA "Invalid marshaling metadata."
IDS_EE_BADMARSHAL_CUSTOMMARSHALER "Custom marshalers are only allowed on classes, strings, arrays, and boxed value types."
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Generic types cannot be marshaled."
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Non-blittable generic types cannot be marshaled."
IDS_EE_BADMARSHAL_STRING_OUT "Cannot marshal a string by-value with the [Out] attribute."

IDS_EE_BADMARSHALPARAM_STRINGBUILDER "Invalid managed/unmanaged type combination (StringBuilders must be paired with LPStr, LPWStr, or LPTStr)."
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -334,13 +334,29 @@ internal static MarshallerKind GetMarshallerKind(
return MarshallerKind.Invalid;
}

if (type.HasInstantiation)
bool isBlittable = MarshalUtils.IsBlittableType(type);

// Blittable generics are allowed to be marshalled with the following exceptions:
// * ByReference<T>: This represents an interior pointer and is not actually blittable
// * Nullable<T>: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
// * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios

if (type.HasInstantiation && (!isBlittable
|| InteropTypes.IsSystemByReference(context, type)
|| InteropTypes.IsSystemNullable(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector64T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector128T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector256T(context, type)
|| InteropTypes.IsSystemNumericsVectorT(context, type)))
{
// Generic types cannot be marshaled.
return MarshallerKind.Invalid;
}

if (MarshalUtils.IsBlittableType(type))
if (isBlittable)
{
if (nativeType != NativeTypeKind.Default && nativeType != NativeTypeKind.Struct)
return MarshallerKind.Invalid;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -108,6 +108,36 @@ public static bool IsSystemArgIterator(TypeSystemContext context, TypeDesc type)
return IsCoreNamedType(context, type, "System", "ArgIterator");
}

public static bool IsSystemByReference(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "ByReference`1");
}

public static bool IsSystemNullable(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "Nullable`1");
}

public static bool IsSystemRuntimeIntrinsicsVector64T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector64`1");
}

public static bool IsSystemRuntimeIntrinsicsVector128T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector128`1");
}

public static bool IsSystemRuntimeIntrinsicsVector256T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector256`1");
}

public static bool IsSystemNumericsVectorT(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Numerics", "Vector`1");
}

private static bool IsOrDerivesFromType(TypeDesc type, MetadataType targetType)
{
while (type != null)
Expand Down
22 changes: 20 additions & 2 deletions src/coreclr/src/vm/mlinfo.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -2796,7 +2796,25 @@ MarshalInfo::MarshalInfo(Module* pModule,
}
#endif // FEATURE_COMINTEROP

if (m_pMT->HasInstantiation())
// Blittable generics are allowed to be marshalled with the following exceptions:
// * ByReference<T>: This represents an interior pointer and is not actually blittable
// * Nullable<T>: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
// * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios

if (m_pMT->HasInstantiation() && (!m_pMT->IsBlittable()
|| m_pMT->HasSameTypeDefAs(g_pByReferenceClass)
|| m_pMT->HasSameTypeDefAs(g_pNullableClass)
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR64T))
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR128T))
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR256T))
#ifndef CROSSGEN_COMPILE
// Crossgen scenarios block Vector<T> from even being loaded
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTORT))
#endif // !CROSSGEN_COMPILE
))
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
Expand DownExpand Up@@ -2916,7 +2934,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
if (m_ms != MARSHAL_SCENARIO_WINRT)
#endif // FEATURE_COMINTEROP
{
if (thElement.HasInstantiation())
if (thElement.HasInstantiation() && !thElement.IsBlittable())
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/src/vm/mscorlib.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -499,6 +499,14 @@ DEFINE_FIELD(MARSHAL, SYSTEM_MAX_DBCS_CHAR_SIZE, SystemMax
DEFINE_CLASS(NATIVELIBRARY, Interop, NativeLibrary)
DEFINE_METHOD(NATIVELIBRARY, LOADLIBRARYCALLBACKSTUB, LoadLibraryCallbackStub, SM_Str_AssemblyBase_Bool_UInt_RetIntPtr)

DEFINE_CLASS(VECTOR64T, Intrinsics, Vector64`1)
DEFINE_CLASS(VECTOR128T, Intrinsics, Vector128`1)
DEFINE_CLASS(VECTOR256T, Intrinsics, Vector256`1)

#ifndef CROSSGEN_COMPILE
DEFINE_CLASS(VECTORT, Numerics, Vector`1)
#endif // !CROSSGEN_COMPILE

DEFINE_CLASS(MEMBER, Reflection, MemberInfo)


Expand Down
1 change: 1 addition & 0 deletions src/coreclr/src/vm/namespace.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@
#endif // FEATURE_COMINTEROP

#define g_IntrinsicsNS g_RuntimeNS ".Intrinsics"
#define g_NumericsNS g_SystemNS ".Numerics"

#define g_InternalCompilerServicesNS "Internal.Runtime.CompilerServices"
#define g_CompilerServicesNS g_RuntimeNS ".CompilerServices"
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/tests/src/Interop/CMakeLists.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ add_subdirectory(PInvoke/Miscellaneous/HandleRef)
add_subdirectory(PInvoke/Miscellaneous/ThisCall)
add_subdirectory(PInvoke/Miscellaneous/MultipleAssembliesWithSamePInvoke)
add_subdirectory(PInvoke/CriticalHandles)
add_subdirectory(PInvoke/Generics)
add_subdirectory(PInvoke/AsAny)
add_subdirectory(PInvoke/SafeHandles)
add_subdirectory(NativeCallable)
Expand Down
87 changes: 87 additions & 0 deletions src/coreclr/tests/src/Interop/PInvoke/Generics/CMakeLists.txt
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
cmake_minimum_required (VERSION 2.6)
project (GenericsNative)
include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake")
if(CLR_CMAKE_TARGET_ARCH_I386)
add_definitions(-D_TARGET_X86_)
add_definitions(-D_TARGET_XARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_AMD64)
add_definitions(-D_TARGET_AMD64_)
add_definitions(-D_TARGET_XARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_ARM)
add_definitions(-D_TARGET_ARM_)
add_definitions(-D_TARGET_ARMARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_ARM64)
add_definitions(-D_TARGET_ARM64_)
add_definitions(-D_TARGET_ARMARCH_)
endif()
set(SOURCES
GenericsNative.IUnknown.cpp
GenericsNative.NullableB.cpp
GenericsNative.NullableC.cpp
GenericsNative.NullableD.cpp
GenericsNative.NullableF.cpp
GenericsNative.NullableL.cpp
GenericsNative.NullableU.cpp
GenericsNative.Point1B.cpp
GenericsNative.Point1C.cpp
GenericsNative.Point1D.cpp
GenericsNative.Point1F.cpp
GenericsNative.Point1L.cpp
GenericsNative.Point1U.cpp
GenericsNative.Point2B.cpp
GenericsNative.Point2C.cpp
GenericsNative.Point2D.cpp
GenericsNative.Point2F.cpp
GenericsNative.Point2L.cpp
GenericsNative.Point2U.cpp
GenericsNative.Point3B.cpp
GenericsNative.Point3C.cpp
GenericsNative.Point3D.cpp
GenericsNative.Point3F.cpp
GenericsNative.Point3L.cpp
GenericsNative.Point3U.cpp
GenericsNative.Point4B.cpp
GenericsNative.Point4C.cpp
GenericsNative.Point4D.cpp
GenericsNative.Point4F.cpp
GenericsNative.Point4L.cpp
GenericsNative.Point4U.cpp
GenericsNative.SequentialClassB.cpp
GenericsNative.SequentialClassC.cpp
GenericsNative.SequentialClassD.cpp
GenericsNative.SequentialClassF.cpp
GenericsNative.SequentialClassL.cpp
GenericsNative.SequentialClassU.cpp
GenericsNative.SpanB.cpp
GenericsNative.SpanC.cpp
GenericsNative.SpanD.cpp
GenericsNative.SpanF.cpp
GenericsNative.SpanL.cpp
GenericsNative.SpanU.cpp
GenericsNative.Vector64B.cpp
GenericsNative.Vector64C.cpp
GenericsNative.Vector64D.cpp
GenericsNative.Vector64F.cpp
GenericsNative.Vector64L.cpp
GenericsNative.Vector64U.cpp
GenericsNative.Vector128B.cpp
GenericsNative.Vector128C.cpp
GenericsNative.Vector128D.cpp
GenericsNative.Vector128F.cpp
GenericsNative.Vector128L.cpp
GenericsNative.Vector128U.cpp
GenericsNative.Vector256B.cpp
GenericsNative.Vector256C.cpp
GenericsNative.Vector256D.cpp
GenericsNative.Vector256F.cpp
GenericsNative.Vector256L.cpp
GenericsNative.Vector256U.cpp
GenericsNative.VectorB.cpp
GenericsNative.VectorC.cpp
GenericsNative.VectorD.cpp
GenericsNative.VectorF.cpp
GenericsNative.VectorL.cpp
GenericsNative.VectorU.cpp
)
add_library (GenericsNative SHARED ${SOURCES})
install (TARGETS GenericsNative DESTINATION bin)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

extern "C" DLL_EXPORT IUnknown* STDMETHODCALLTYPE GetIComInterface()
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetIComInterfaceOut(IUnknown** pValue)
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT const IUnknown** STDMETHODCALLTYPE GetIComInterfacePtr()
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetIComInterfaces(IUnknown** pValues, int count)
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableB
{
bool hasValue;
bool value;
};

static NullableB NullableBValue = { };

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE GetNullableB(bool hasValue, bool value)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableBOut(bool hasValue, bool value, NullableB* pValue)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableB* STDMETHODCALLTYPE GetNullableBPtr(bool hasValue, bool value)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE AddNullableB(NullableB lhs, NullableB rhs)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE AddNullableBs(const NullableB* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableC
{
bool hasValue;
char16_t value;
};

static NullableC NullableCValue = { };

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE GetNullableC(bool hasValue, char16_t value)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableCOut(bool hasValue, char16_t value, NullableC* pValue)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableC* STDMETHODCALLTYPE GetNullableCPtr(bool hasValue, char16_t value)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE AddNullableC(NullableC lhs, NullableC rhs)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE AddNullableCs(const NullableC* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Doundation under one or more agreements.
// The .NET Doundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableD
{
bool hasValue;
double value;
};

static NullableD NullableDValue = { };

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE GetNullableD(bool hasValue, double value)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableDOut(bool hasValue, double value, NullableD* pValue)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableD* STDMETHODCALLTYPE GetNullableDPtr(bool hasValue, double value)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE AddNullableD(NullableD lhs, NullableD rhs)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE AddNullableDs(const NullableD* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/src/dlls/mscorrc/mscorrc.rc
Original file line numberDiff line numberDiff line change
Expand Up@@ -627,7 +627,7 @@ BEGIN
IDS_EE_BADMARSHAL_NOTMARSHALABLE "The type definition of this field has layout information but has an invalid managed/unmanaged type combination or is unmarshalable."
IDS_EE_BADMARSHAL_BADMETADATA "Invalid marshaling metadata."
IDS_EE_BADMARSHAL_CUSTOMMARSHALER "Custom marshalers are only allowed on classes, strings, arrays, and boxed value types."
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Generic types cannot be marshaled."
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Non-blittable generic types cannot be marshaled."
IDS_EE_BADMARSHAL_STRING_OUT "Cannot marshal a string by-value with the [Out] attribute."

IDS_EE_BADMARSHALPARAM_STRINGBUILDER "Invalid managed/unmanaged type combination (StringBuilders must be paired with LPStr, LPWStr, or LPTStr)."
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -334,13 +334,29 @@ internal static MarshallerKind GetMarshallerKind(
return MarshallerKind.Invalid;
}

if (type.HasInstantiation)
bool isBlittable = MarshalUtils.IsBlittableType(type);

// Blittable generics are allowed to be marshalled with the following exceptions:
// * ByReference<T>: This represents an interior pointer and is not actually blittable
// * Nullable<T>: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
// * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios

if (type.HasInstantiation && (!isBlittable
|| InteropTypes.IsSystemByReference(context, type)
|| InteropTypes.IsSystemNullable(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector64T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector128T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector256T(context, type)
|| InteropTypes.IsSystemNumericsVectorT(context, type)))
{
// Generic types cannot be marshaled.
return MarshallerKind.Invalid;
}

if (MarshalUtils.IsBlittableType(type))
if (isBlittable)
{
if (nativeType != NativeTypeKind.Default && nativeType != NativeTypeKind.Struct)
return MarshallerKind.Invalid;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -108,6 +108,36 @@ public static bool IsSystemArgIterator(TypeSystemContext context, TypeDesc type)
return IsCoreNamedType(context, type, "System", "ArgIterator");
}

public static bool IsSystemByReference(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "ByReference`1");
}

public static bool IsSystemNullable(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "Nullable`1");
}

public static bool IsSystemRuntimeIntrinsicsVector64T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector64`1");
}

public static bool IsSystemRuntimeIntrinsicsVector128T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector128`1");
}

public static bool IsSystemRuntimeIntrinsicsVector256T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector256`1");
}

public static bool IsSystemNumericsVectorT(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Numerics", "Vector`1");
}

private static bool IsOrDerivesFromType(TypeDesc type, MetadataType targetType)
{
while (type != null)
Expand Down
22 changes: 20 additions & 2 deletions src/coreclr/src/vm/mlinfo.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -2796,7 +2796,25 @@ MarshalInfo::MarshalInfo(Module* pModule,
}
#endif // FEATURE_COMINTEROP

if (m_pMT->HasInstantiation())
// Blittable generics are allowed to be marshalled with the following exceptions:
// * ByReference<T>: This represents an interior pointer and is not actually blittable
// * Nullable<T>: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
// * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios

if (m_pMT->HasInstantiation() && (!m_pMT->IsBlittable()
|| m_pMT->HasSameTypeDefAs(g_pByReferenceClass)
|| m_pMT->HasSameTypeDefAs(g_pNullableClass)
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR64T))
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR128T))
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR256T))
#ifndef CROSSGEN_COMPILE
// Crossgen scenarios block Vector<T> from even being loaded
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTORT))
#endif // !CROSSGEN_COMPILE
))
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
Expand DownExpand Up@@ -2916,7 +2934,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
if (m_ms != MARSHAL_SCENARIO_WINRT)
#endif // FEATURE_COMINTEROP
{
if (thElement.HasInstantiation())
if (thElement.HasInstantiation() && !thElement.IsBlittable())
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/src/vm/mscorlib.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -499,6 +499,14 @@ DEFINE_FIELD(MARSHAL, SYSTEM_MAX_DBCS_CHAR_SIZE, SystemMax
DEFINE_CLASS(NATIVELIBRARY, Interop, NativeLibrary)
DEFINE_METHOD(NATIVELIBRARY, LOADLIBRARYCALLBACKSTUB, LoadLibraryCallbackStub, SM_Str_AssemblyBase_Bool_UInt_RetIntPtr)

DEFINE_CLASS(VECTOR64T, Intrinsics, Vector64`1)
DEFINE_CLASS(VECTOR128T, Intrinsics, Vector128`1)
DEFINE_CLASS(VECTOR256T, Intrinsics, Vector256`1)

#ifndef CROSSGEN_COMPILE
DEFINE_CLASS(VECTORT, Numerics, Vector`1)
#endif // !CROSSGEN_COMPILE

DEFINE_CLASS(MEMBER, Reflection, MemberInfo)


Expand Down
1 change: 1 addition & 0 deletions src/coreclr/src/vm/namespace.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@
#endif // FEATURE_COMINTEROP

#define g_IntrinsicsNS g_RuntimeNS ".Intrinsics"
#define g_NumericsNS g_SystemNS ".Numerics"

#define g_InternalCompilerServicesNS "Internal.Runtime.CompilerServices"
#define g_CompilerServicesNS g_RuntimeNS ".CompilerServices"
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/tests/src/Interop/CMakeLists.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ add_subdirectory(PInvoke/Miscellaneous/HandleRef)
add_subdirectory(PInvoke/Miscellaneous/ThisCall)
add_subdirectory(PInvoke/Miscellaneous/MultipleAssembliesWithSamePInvoke)
add_subdirectory(PInvoke/CriticalHandles)
add_subdirectory(PInvoke/Generics)
add_subdirectory(PInvoke/AsAny)
add_subdirectory(PInvoke/SafeHandles)
add_subdirectory(NativeCallable)
Expand Down
87 changes: 87 additions & 0 deletions src/coreclr/tests/src/Interop/PInvoke/Generics/CMakeLists.txt
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
cmake_minimum_required (VERSION 2.6)
project (GenericsNative)
include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake")
if(CLR_CMAKE_TARGET_ARCH_I386)
add_definitions(-D_TARGET_X86_)
add_definitions(-D_TARGET_XARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_AMD64)
add_definitions(-D_TARGET_AMD64_)
add_definitions(-D_TARGET_XARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_ARM)
add_definitions(-D_TARGET_ARM_)
add_definitions(-D_TARGET_ARMARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_ARM64)
add_definitions(-D_TARGET_ARM64_)
add_definitions(-D_TARGET_ARMARCH_)
endif()
set(SOURCES
GenericsNative.IUnknown.cpp
GenericsNative.NullableB.cpp
GenericsNative.NullableC.cpp
GenericsNative.NullableD.cpp
GenericsNative.NullableF.cpp
GenericsNative.NullableL.cpp
GenericsNative.NullableU.cpp
GenericsNative.Point1B.cpp
GenericsNative.Point1C.cpp
GenericsNative.Point1D.cpp
GenericsNative.Point1F.cpp
GenericsNative.Point1L.cpp
GenericsNative.Point1U.cpp
GenericsNative.Point2B.cpp
GenericsNative.Point2C.cpp
GenericsNative.Point2D.cpp
GenericsNative.Point2F.cpp
GenericsNative.Point2L.cpp
GenericsNative.Point2U.cpp
GenericsNative.Point3B.cpp
GenericsNative.Point3C.cpp
GenericsNative.Point3D.cpp
GenericsNative.Point3F.cpp
GenericsNative.Point3L.cpp
GenericsNative.Point3U.cpp
GenericsNative.Point4B.cpp
GenericsNative.Point4C.cpp
GenericsNative.Point4D.cpp
GenericsNative.Point4F.cpp
GenericsNative.Point4L.cpp
GenericsNative.Point4U.cpp
GenericsNative.SequentialClassB.cpp
GenericsNative.SequentialClassC.cpp
GenericsNative.SequentialClassD.cpp
GenericsNative.SequentialClassF.cpp
GenericsNative.SequentialClassL.cpp
GenericsNative.SequentialClassU.cpp
GenericsNative.SpanB.cpp
GenericsNative.SpanC.cpp
GenericsNative.SpanD.cpp
GenericsNative.SpanF.cpp
GenericsNative.SpanL.cpp
GenericsNative.SpanU.cpp
GenericsNative.Vector64B.cpp
GenericsNative.Vector64C.cpp
GenericsNative.Vector64D.cpp
GenericsNative.Vector64F.cpp
GenericsNative.Vector64L.cpp
GenericsNative.Vector64U.cpp
GenericsNative.Vector128B.cpp
GenericsNative.Vector128C.cpp
GenericsNative.Vector128D.cpp
GenericsNative.Vector128F.cpp
GenericsNative.Vector128L.cpp
GenericsNative.Vector128U.cpp
GenericsNative.Vector256B.cpp
GenericsNative.Vector256C.cpp
GenericsNative.Vector256D.cpp
GenericsNative.Vector256F.cpp
GenericsNative.Vector256L.cpp
GenericsNative.Vector256U.cpp
GenericsNative.VectorB.cpp
GenericsNative.VectorC.cpp
GenericsNative.VectorD.cpp
GenericsNative.VectorF.cpp
GenericsNative.VectorL.cpp
GenericsNative.VectorU.cpp
)
add_library (GenericsNative SHARED ${SOURCES})
install (TARGETS GenericsNative DESTINATION bin)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

extern "C" DLL_EXPORT IUnknown* STDMETHODCALLTYPE GetIComInterface()
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetIComInterfaceOut(IUnknown** pValue)
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT const IUnknown** STDMETHODCALLTYPE GetIComInterfacePtr()
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetIComInterfaces(IUnknown** pValues, int count)
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableB
{
bool hasValue;
bool value;
};

static NullableB NullableBValue = { };

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE GetNullableB(bool hasValue, bool value)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableBOut(bool hasValue, bool value, NullableB* pValue)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableB* STDMETHODCALLTYPE GetNullableBPtr(bool hasValue, bool value)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE AddNullableB(NullableB lhs, NullableB rhs)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE AddNullableBs(const NullableB* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableC
{
bool hasValue;
char16_t value;
};

static NullableC NullableCValue = { };

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE GetNullableC(bool hasValue, char16_t value)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableCOut(bool hasValue, char16_t value, NullableC* pValue)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableC* STDMETHODCALLTYPE GetNullableCPtr(bool hasValue, char16_t value)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE AddNullableC(NullableC lhs, NullableC rhs)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE AddNullableCs(const NullableC* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Doundation under one or more agreements.
// The .NET Doundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableD
{
bool hasValue;
double value;
};

static NullableD NullableDValue = { };

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE GetNullableD(bool hasValue, double value)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableDOut(bool hasValue, double value, NullableD* pValue)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableD* STDMETHODCALLTYPE GetNullableDPtr(bool hasValue, double value)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE AddNullableD(NullableD lhs, NullableD rhs)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE AddNullableDs(const NullableD* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/src/dlls/mscorrc/mscorrc.rc
Original file line numberDiff line numberDiff line change
Expand Up@@ -627,7 +627,7 @@ BEGIN
IDS_EE_BADMARSHAL_NOTMARSHALABLE "The type definition of this field has layout information but has an invalid managed/unmanaged type combination or is unmarshalable."
IDS_EE_BADMARSHAL_BADMETADATA "Invalid marshaling metadata."
IDS_EE_BADMARSHAL_CUSTOMMARSHALER "Custom marshalers are only allowed on classes, strings, arrays, and boxed value types."
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Generic types cannot be marshaled."
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Non-blittable generic types cannot be marshaled."
IDS_EE_BADMARSHAL_STRING_OUT "Cannot marshal a string by-value with the [Out] attribute."

IDS_EE_BADMARSHALPARAM_STRINGBUILDER "Invalid managed/unmanaged type combination (StringBuilders must be paired with LPStr, LPWStr, or LPTStr)."
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -334,13 +334,29 @@ internal static MarshallerKind GetMarshallerKind(
return MarshallerKind.Invalid;
}

if (type.HasInstantiation)
bool isBlittable = MarshalUtils.IsBlittableType(type);

// Blittable generics are allowed to be marshalled with the following exceptions:
// * ByReference<T>: This represents an interior pointer and is not actually blittable
// * Nullable<T>: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
// * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios

if (type.HasInstantiation && (!isBlittable
|| InteropTypes.IsSystemByReference(context, type)
|| InteropTypes.IsSystemNullable(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector64T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector128T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector256T(context, type)
|| InteropTypes.IsSystemNumericsVectorT(context, type)))
{
// Generic types cannot be marshaled.
return MarshallerKind.Invalid;
}

if (MarshalUtils.IsBlittableType(type))
if (isBlittable)
{
if (nativeType != NativeTypeKind.Default && nativeType != NativeTypeKind.Struct)
return MarshallerKind.Invalid;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -108,6 +108,36 @@ public static bool IsSystemArgIterator(TypeSystemContext context, TypeDesc type)
return IsCoreNamedType(context, type, "System", "ArgIterator");
}

public static bool IsSystemByReference(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "ByReference`1");
}

public static bool IsSystemNullable(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "Nullable`1");
}

public static bool IsSystemRuntimeIntrinsicsVector64T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector64`1");
}

public static bool IsSystemRuntimeIntrinsicsVector128T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector128`1");
}

public static bool IsSystemRuntimeIntrinsicsVector256T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector256`1");
}

public static bool IsSystemNumericsVectorT(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Numerics", "Vector`1");
}

private static bool IsOrDerivesFromType(TypeDesc type, MetadataType targetType)
{
while (type != null)
Expand Down
22 changes: 20 additions & 2 deletions src/coreclr/src/vm/mlinfo.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -2796,7 +2796,25 @@ MarshalInfo::MarshalInfo(Module* pModule,
}
#endif // FEATURE_COMINTEROP

if (m_pMT->HasInstantiation())
// Blittable generics are allowed to be marshalled with the following exceptions:
// * ByReference<T>: This represents an interior pointer and is not actually blittable
// * Nullable<T>: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
// * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios

if (m_pMT->HasInstantiation() && (!m_pMT->IsBlittable()
|| m_pMT->HasSameTypeDefAs(g_pByReferenceClass)
|| m_pMT->HasSameTypeDefAs(g_pNullableClass)
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR64T))
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR128T))
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR256T))
#ifndef CROSSGEN_COMPILE
// Crossgen scenarios block Vector<T> from even being loaded
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTORT))
#endif // !CROSSGEN_COMPILE
))
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
Expand DownExpand Up@@ -2916,7 +2934,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
if (m_ms != MARSHAL_SCENARIO_WINRT)
#endif // FEATURE_COMINTEROP
{
if (thElement.HasInstantiation())
if (thElement.HasInstantiation() && !thElement.IsBlittable())
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/src/vm/mscorlib.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -499,6 +499,14 @@ DEFINE_FIELD(MARSHAL, SYSTEM_MAX_DBCS_CHAR_SIZE, SystemMax
DEFINE_CLASS(NATIVELIBRARY, Interop, NativeLibrary)
DEFINE_METHOD(NATIVELIBRARY, LOADLIBRARYCALLBACKSTUB, LoadLibraryCallbackStub, SM_Str_AssemblyBase_Bool_UInt_RetIntPtr)

DEFINE_CLASS(VECTOR64T, Intrinsics, Vector64`1)
DEFINE_CLASS(VECTOR128T, Intrinsics, Vector128`1)
DEFINE_CLASS(VECTOR256T, Intrinsics, Vector256`1)

#ifndef CROSSGEN_COMPILE
DEFINE_CLASS(VECTORT, Numerics, Vector`1)
#endif // !CROSSGEN_COMPILE

DEFINE_CLASS(MEMBER, Reflection, MemberInfo)


Expand Down
1 change: 1 addition & 0 deletions src/coreclr/src/vm/namespace.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@
#endif // FEATURE_COMINTEROP

#define g_IntrinsicsNS g_RuntimeNS ".Intrinsics"
#define g_NumericsNS g_SystemNS ".Numerics"

#define g_InternalCompilerServicesNS "Internal.Runtime.CompilerServices"
#define g_CompilerServicesNS g_RuntimeNS ".CompilerServices"
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/tests/src/Interop/CMakeLists.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ add_subdirectory(PInvoke/Miscellaneous/HandleRef)
add_subdirectory(PInvoke/Miscellaneous/ThisCall)
add_subdirectory(PInvoke/Miscellaneous/MultipleAssembliesWithSamePInvoke)
add_subdirectory(PInvoke/CriticalHandles)
add_subdirectory(PInvoke/Generics)
add_subdirectory(PInvoke/AsAny)
add_subdirectory(PInvoke/SafeHandles)
add_subdirectory(NativeCallable)
Expand Down
87 changes: 87 additions & 0 deletions src/coreclr/tests/src/Interop/PInvoke/Generics/CMakeLists.txt
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
cmake_minimum_required (VERSION 2.6)
project (GenericsNative)
include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake")
if(CLR_CMAKE_TARGET_ARCH_I386)
add_definitions(-D_TARGET_X86_)
add_definitions(-D_TARGET_XARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_AMD64)
add_definitions(-D_TARGET_AMD64_)
add_definitions(-D_TARGET_XARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_ARM)
add_definitions(-D_TARGET_ARM_)
add_definitions(-D_TARGET_ARMARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_ARM64)
add_definitions(-D_TARGET_ARM64_)
add_definitions(-D_TARGET_ARMARCH_)
endif()
set(SOURCES
GenericsNative.IUnknown.cpp
GenericsNative.NullableB.cpp
GenericsNative.NullableC.cpp
GenericsNative.NullableD.cpp
GenericsNative.NullableF.cpp
GenericsNative.NullableL.cpp
GenericsNative.NullableU.cpp
GenericsNative.Point1B.cpp
GenericsNative.Point1C.cpp
GenericsNative.Point1D.cpp
GenericsNative.Point1F.cpp
GenericsNative.Point1L.cpp
GenericsNative.Point1U.cpp
GenericsNative.Point2B.cpp
GenericsNative.Point2C.cpp
GenericsNative.Point2D.cpp
GenericsNative.Point2F.cpp
GenericsNative.Point2L.cpp
GenericsNative.Point2U.cpp
GenericsNative.Point3B.cpp
GenericsNative.Point3C.cpp
GenericsNative.Point3D.cpp
GenericsNative.Point3F.cpp
GenericsNative.Point3L.cpp
GenericsNative.Point3U.cpp
GenericsNative.Point4B.cpp
GenericsNative.Point4C.cpp
GenericsNative.Point4D.cpp
GenericsNative.Point4F.cpp
GenericsNative.Point4L.cpp
GenericsNative.Point4U.cpp
GenericsNative.SequentialClassB.cpp
GenericsNative.SequentialClassC.cpp
GenericsNative.SequentialClassD.cpp
GenericsNative.SequentialClassF.cpp
GenericsNative.SequentialClassL.cpp
GenericsNative.SequentialClassU.cpp
GenericsNative.SpanB.cpp
GenericsNative.SpanC.cpp
GenericsNative.SpanD.cpp
GenericsNative.SpanF.cpp
GenericsNative.SpanL.cpp
GenericsNative.SpanU.cpp
GenericsNative.Vector64B.cpp
GenericsNative.Vector64C.cpp
GenericsNative.Vector64D.cpp
GenericsNative.Vector64F.cpp
GenericsNative.Vector64L.cpp
GenericsNative.Vector64U.cpp
GenericsNative.Vector128B.cpp
GenericsNative.Vector128C.cpp
GenericsNative.Vector128D.cpp
GenericsNative.Vector128F.cpp
GenericsNative.Vector128L.cpp
GenericsNative.Vector128U.cpp
GenericsNative.Vector256B.cpp
GenericsNative.Vector256C.cpp
GenericsNative.Vector256D.cpp
GenericsNative.Vector256F.cpp
GenericsNative.Vector256L.cpp
GenericsNative.Vector256U.cpp
GenericsNative.VectorB.cpp
GenericsNative.VectorC.cpp
GenericsNative.VectorD.cpp
GenericsNative.VectorF.cpp
GenericsNative.VectorL.cpp
GenericsNative.VectorU.cpp
)
add_library (GenericsNative SHARED ${SOURCES})
install (TARGETS GenericsNative DESTINATION bin)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

extern "C" DLL_EXPORT IUnknown* STDMETHODCALLTYPE GetIComInterface()
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetIComInterfaceOut(IUnknown** pValue)
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT const IUnknown** STDMETHODCALLTYPE GetIComInterfacePtr()
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetIComInterfaces(IUnknown** pValues, int count)
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableB
{
bool hasValue;
bool value;
};

static NullableB NullableBValue = { };

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE GetNullableB(bool hasValue, bool value)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableBOut(bool hasValue, bool value, NullableB* pValue)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableB* STDMETHODCALLTYPE GetNullableBPtr(bool hasValue, bool value)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE AddNullableB(NullableB lhs, NullableB rhs)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE AddNullableBs(const NullableB* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableC
{
bool hasValue;
char16_t value;
};

static NullableC NullableCValue = { };

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE GetNullableC(bool hasValue, char16_t value)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableCOut(bool hasValue, char16_t value, NullableC* pValue)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableC* STDMETHODCALLTYPE GetNullableCPtr(bool hasValue, char16_t value)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE AddNullableC(NullableC lhs, NullableC rhs)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE AddNullableCs(const NullableC* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Doundation under one or more agreements.
// The .NET Doundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableD
{
bool hasValue;
double value;
};

static NullableD NullableDValue = { };

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE GetNullableD(bool hasValue, double value)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableDOut(bool hasValue, double value, NullableD* pValue)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableD* STDMETHODCALLTYPE GetNullableDPtr(bool hasValue, double value)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE AddNullableD(NullableD lhs, NullableD rhs)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE AddNullableDs(const NullableD* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/src/dlls/mscorrc/mscorrc.rc
Original file line numberDiff line numberDiff line change
Expand Up@@ -627,7 +627,7 @@ BEGIN
IDS_EE_BADMARSHAL_NOTMARSHALABLE "The type definition of this field has layout information but has an invalid managed/unmanaged type combination or is unmarshalable."
IDS_EE_BADMARSHAL_BADMETADATA "Invalid marshaling metadata."
IDS_EE_BADMARSHAL_CUSTOMMARSHALER "Custom marshalers are only allowed on classes, strings, arrays, and boxed value types."
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Generic types cannot be marshaled."
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Non-blittable generic types cannot be marshaled."
IDS_EE_BADMARSHAL_STRING_OUT "Cannot marshal a string by-value with the [Out] attribute."

IDS_EE_BADMARSHALPARAM_STRINGBUILDER "Invalid managed/unmanaged type combination (StringBuilders must be paired with LPStr, LPWStr, or LPTStr)."
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -334,13 +334,29 @@ internal static MarshallerKind GetMarshallerKind(
return MarshallerKind.Invalid;
}

if (type.HasInstantiation)
bool isBlittable = MarshalUtils.IsBlittableType(type);

// Blittable generics are allowed to be marshalled with the following exceptions:
// * ByReference<T>: This represents an interior pointer and is not actually blittable
// * Nullable<T>: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
// * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios

if (type.HasInstantiation && (!isBlittable
|| InteropTypes.IsSystemByReference(context, type)
|| InteropTypes.IsSystemNullable(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector64T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector128T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector256T(context, type)
|| InteropTypes.IsSystemNumericsVectorT(context, type)))
{
// Generic types cannot be marshaled.
return MarshallerKind.Invalid;
}

if (MarshalUtils.IsBlittableType(type))
if (isBlittable)
{
if (nativeType != NativeTypeKind.Default && nativeType != NativeTypeKind.Struct)
return MarshallerKind.Invalid;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -108,6 +108,36 @@ public static bool IsSystemArgIterator(TypeSystemContext context, TypeDesc type)
return IsCoreNamedType(context, type, "System", "ArgIterator");
}

public static bool IsSystemByReference(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "ByReference`1");
}

public static bool IsSystemNullable(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "Nullable`1");
}

public static bool IsSystemRuntimeIntrinsicsVector64T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector64`1");
}

public static bool IsSystemRuntimeIntrinsicsVector128T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector128`1");
}

public static bool IsSystemRuntimeIntrinsicsVector256T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector256`1");
}

public static bool IsSystemNumericsVectorT(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Numerics", "Vector`1");
}

private static bool IsOrDerivesFromType(TypeDesc type, MetadataType targetType)
{
while (type != null)
Expand Down
22 changes: 20 additions & 2 deletions src/coreclr/src/vm/mlinfo.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -2796,7 +2796,25 @@ MarshalInfo::MarshalInfo(Module* pModule,
}
#endif // FEATURE_COMINTEROP

if (m_pMT->HasInstantiation())
// Blittable generics are allowed to be marshalled with the following exceptions:
// * ByReference<T>: This represents an interior pointer and is not actually blittable
// * Nullable<T>: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
// * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios

if (m_pMT->HasInstantiation() && (!m_pMT->IsBlittable()
|| m_pMT->HasSameTypeDefAs(g_pByReferenceClass)
|| m_pMT->HasSameTypeDefAs(g_pNullableClass)
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR64T))
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR128T))
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR256T))
#ifndef CROSSGEN_COMPILE
// Crossgen scenarios block Vector<T> from even being loaded
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTORT))
#endif // !CROSSGEN_COMPILE
))
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
Expand DownExpand Up@@ -2916,7 +2934,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
if (m_ms != MARSHAL_SCENARIO_WINRT)
#endif // FEATURE_COMINTEROP
{
if (thElement.HasInstantiation())
if (thElement.HasInstantiation() && !thElement.IsBlittable())
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/src/vm/mscorlib.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -499,6 +499,14 @@ DEFINE_FIELD(MARSHAL, SYSTEM_MAX_DBCS_CHAR_SIZE, SystemMax
DEFINE_CLASS(NATIVELIBRARY, Interop, NativeLibrary)
DEFINE_METHOD(NATIVELIBRARY, LOADLIBRARYCALLBACKSTUB, LoadLibraryCallbackStub, SM_Str_AssemblyBase_Bool_UInt_RetIntPtr)

DEFINE_CLASS(VECTOR64T, Intrinsics, Vector64`1)
DEFINE_CLASS(VECTOR128T, Intrinsics, Vector128`1)
DEFINE_CLASS(VECTOR256T, Intrinsics, Vector256`1)

#ifndef CROSSGEN_COMPILE
DEFINE_CLASS(VECTORT, Numerics, Vector`1)
#endif // !CROSSGEN_COMPILE

DEFINE_CLASS(MEMBER, Reflection, MemberInfo)


Expand Down
1 change: 1 addition & 0 deletions src/coreclr/src/vm/namespace.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@
#endif // FEATURE_COMINTEROP

#define g_IntrinsicsNS g_RuntimeNS ".Intrinsics"
#define g_NumericsNS g_SystemNS ".Numerics"

#define g_InternalCompilerServicesNS "Internal.Runtime.CompilerServices"
#define g_CompilerServicesNS g_RuntimeNS ".CompilerServices"
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/tests/src/Interop/CMakeLists.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ add_subdirectory(PInvoke/Miscellaneous/HandleRef)
add_subdirectory(PInvoke/Miscellaneous/ThisCall)
add_subdirectory(PInvoke/Miscellaneous/MultipleAssembliesWithSamePInvoke)
add_subdirectory(PInvoke/CriticalHandles)
add_subdirectory(PInvoke/Generics)
add_subdirectory(PInvoke/AsAny)
add_subdirectory(PInvoke/SafeHandles)
add_subdirectory(NativeCallable)
Expand Down
87 changes: 87 additions & 0 deletions src/coreclr/tests/src/Interop/PInvoke/Generics/CMakeLists.txt
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
cmake_minimum_required (VERSION 2.6)
project (GenericsNative)
include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake")
if(CLR_CMAKE_TARGET_ARCH_I386)
add_definitions(-D_TARGET_X86_)
add_definitions(-D_TARGET_XARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_AMD64)
add_definitions(-D_TARGET_AMD64_)
add_definitions(-D_TARGET_XARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_ARM)
add_definitions(-D_TARGET_ARM_)
add_definitions(-D_TARGET_ARMARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_ARM64)
add_definitions(-D_TARGET_ARM64_)
add_definitions(-D_TARGET_ARMARCH_)
endif()
set(SOURCES
GenericsNative.IUnknown.cpp
GenericsNative.NullableB.cpp
GenericsNative.NullableC.cpp
GenericsNative.NullableD.cpp
GenericsNative.NullableF.cpp
GenericsNative.NullableL.cpp
GenericsNative.NullableU.cpp
GenericsNative.Point1B.cpp
GenericsNative.Point1C.cpp
GenericsNative.Point1D.cpp
GenericsNative.Point1F.cpp
GenericsNative.Point1L.cpp
GenericsNative.Point1U.cpp
GenericsNative.Point2B.cpp
GenericsNative.Point2C.cpp
GenericsNative.Point2D.cpp
GenericsNative.Point2F.cpp
GenericsNative.Point2L.cpp
GenericsNative.Point2U.cpp
GenericsNative.Point3B.cpp
GenericsNative.Point3C.cpp
GenericsNative.Point3D.cpp
GenericsNative.Point3F.cpp
GenericsNative.Point3L.cpp
GenericsNative.Point3U.cpp
GenericsNative.Point4B.cpp
GenericsNative.Point4C.cpp
GenericsNative.Point4D.cpp
GenericsNative.Point4F.cpp
GenericsNative.Point4L.cpp
GenericsNative.Point4U.cpp
GenericsNative.SequentialClassB.cpp
GenericsNative.SequentialClassC.cpp
GenericsNative.SequentialClassD.cpp
GenericsNative.SequentialClassF.cpp
GenericsNative.SequentialClassL.cpp
GenericsNative.SequentialClassU.cpp
GenericsNative.SpanB.cpp
GenericsNative.SpanC.cpp
GenericsNative.SpanD.cpp
GenericsNative.SpanF.cpp
GenericsNative.SpanL.cpp
GenericsNative.SpanU.cpp
GenericsNative.Vector64B.cpp
GenericsNative.Vector64C.cpp
GenericsNative.Vector64D.cpp
GenericsNative.Vector64F.cpp
GenericsNative.Vector64L.cpp
GenericsNative.Vector64U.cpp
GenericsNative.Vector128B.cpp
GenericsNative.Vector128C.cpp
GenericsNative.Vector128D.cpp
GenericsNative.Vector128F.cpp
GenericsNative.Vector128L.cpp
GenericsNative.Vector128U.cpp
GenericsNative.Vector256B.cpp
GenericsNative.Vector256C.cpp
GenericsNative.Vector256D.cpp
GenericsNative.Vector256F.cpp
GenericsNative.Vector256L.cpp
GenericsNative.Vector256U.cpp
GenericsNative.VectorB.cpp
GenericsNative.VectorC.cpp
GenericsNative.VectorD.cpp
GenericsNative.VectorF.cpp
GenericsNative.VectorL.cpp
GenericsNative.VectorU.cpp
)
add_library (GenericsNative SHARED ${SOURCES})
install (TARGETS GenericsNative DESTINATION bin)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

extern "C" DLL_EXPORT IUnknown* STDMETHODCALLTYPE GetIComInterface()
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetIComInterfaceOut(IUnknown** pValue)
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT const IUnknown** STDMETHODCALLTYPE GetIComInterfacePtr()
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetIComInterfaces(IUnknown** pValues, int count)
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableB
{
bool hasValue;
bool value;
};

static NullableB NullableBValue = { };

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE GetNullableB(bool hasValue, bool value)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableBOut(bool hasValue, bool value, NullableB* pValue)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableB* STDMETHODCALLTYPE GetNullableBPtr(bool hasValue, bool value)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE AddNullableB(NullableB lhs, NullableB rhs)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE AddNullableBs(const NullableB* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableC
{
bool hasValue;
char16_t value;
};

static NullableC NullableCValue = { };

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE GetNullableC(bool hasValue, char16_t value)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableCOut(bool hasValue, char16_t value, NullableC* pValue)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableC* STDMETHODCALLTYPE GetNullableCPtr(bool hasValue, char16_t value)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE AddNullableC(NullableC lhs, NullableC rhs)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE AddNullableCs(const NullableC* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Doundation under one or more agreements.
// The .NET Doundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableD
{
bool hasValue;
double value;
};

static NullableD NullableDValue = { };

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE GetNullableD(bool hasValue, double value)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableDOut(bool hasValue, double value, NullableD* pValue)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableD* STDMETHODCALLTYPE GetNullableDPtr(bool hasValue, double value)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE AddNullableD(NullableD lhs, NullableD rhs)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE AddNullableDs(const NullableD* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/src/dlls/mscorrc/mscorrc.rc
Original file line numberDiff line numberDiff line change
Expand Up@@ -627,7 +627,7 @@ BEGIN
IDS_EE_BADMARSHAL_NOTMARSHALABLE "The type definition of this field has layout information but has an invalid managed/unmanaged type combination or is unmarshalable."
IDS_EE_BADMARSHAL_BADMETADATA "Invalid marshaling metadata."
IDS_EE_BADMARSHAL_CUSTOMMARSHALER "Custom marshalers are only allowed on classes, strings, arrays, and boxed value types."
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Generic types cannot be marshaled."
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Non-blittable generic types cannot be marshaled."
IDS_EE_BADMARSHAL_STRING_OUT "Cannot marshal a string by-value with the [Out] attribute."

IDS_EE_BADMARSHALPARAM_STRINGBUILDER "Invalid managed/unmanaged type combination (StringBuilders must be paired with LPStr, LPWStr, or LPTStr)."
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -334,13 +334,29 @@ internal static MarshallerKind GetMarshallerKind(
return MarshallerKind.Invalid;
}

if (type.HasInstantiation)
bool isBlittable = MarshalUtils.IsBlittableType(type);

// Blittable generics are allowed to be marshalled with the following exceptions:
// * ByReference<T>: This represents an interior pointer and is not actually blittable
// * Nullable<T>: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
// * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios

if (type.HasInstantiation && (!isBlittable
|| InteropTypes.IsSystemByReference(context, type)
|| InteropTypes.IsSystemNullable(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector64T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector128T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector256T(context, type)
|| InteropTypes.IsSystemNumericsVectorT(context, type)))
{
// Generic types cannot be marshaled.
return MarshallerKind.Invalid;
}

if (MarshalUtils.IsBlittableType(type))
if (isBlittable)
{
if (nativeType != NativeTypeKind.Default && nativeType != NativeTypeKind.Struct)
return MarshallerKind.Invalid;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -108,6 +108,36 @@ public static bool IsSystemArgIterator(TypeSystemContext context, TypeDesc type)
return IsCoreNamedType(context, type, "System", "ArgIterator");
}

public static bool IsSystemByReference(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "ByReference`1");
}

public static bool IsSystemNullable(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "Nullable`1");
}

public static bool IsSystemRuntimeIntrinsicsVector64T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector64`1");
}

public static bool IsSystemRuntimeIntrinsicsVector128T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector128`1");
}

public static bool IsSystemRuntimeIntrinsicsVector256T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector256`1");
}

public static bool IsSystemNumericsVectorT(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Numerics", "Vector`1");
}

private static bool IsOrDerivesFromType(TypeDesc type, MetadataType targetType)
{
while (type != null)
Expand Down
22 changes: 20 additions & 2 deletions src/coreclr/src/vm/mlinfo.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -2796,7 +2796,25 @@ MarshalInfo::MarshalInfo(Module* pModule,
}
#endif // FEATURE_COMINTEROP

if (m_pMT->HasInstantiation())
// Blittable generics are allowed to be marshalled with the following exceptions:
// * ByReference<T>: This represents an interior pointer and is not actually blittable
// * Nullable<T>: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
// * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios

if (m_pMT->HasInstantiation() && (!m_pMT->IsBlittable()
|| m_pMT->HasSameTypeDefAs(g_pByReferenceClass)
|| m_pMT->HasSameTypeDefAs(g_pNullableClass)
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR64T))
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR128T))
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR256T))
#ifndef CROSSGEN_COMPILE
// Crossgen scenarios block Vector<T> from even being loaded
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTORT))
#endif // !CROSSGEN_COMPILE
))
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
Expand DownExpand Up@@ -2916,7 +2934,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
if (m_ms != MARSHAL_SCENARIO_WINRT)
#endif // FEATURE_COMINTEROP
{
if (thElement.HasInstantiation())
if (thElement.HasInstantiation() && !thElement.IsBlittable())
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/src/vm/mscorlib.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -499,6 +499,14 @@ DEFINE_FIELD(MARSHAL, SYSTEM_MAX_DBCS_CHAR_SIZE, SystemMax
DEFINE_CLASS(NATIVELIBRARY, Interop, NativeLibrary)
DEFINE_METHOD(NATIVELIBRARY, LOADLIBRARYCALLBACKSTUB, LoadLibraryCallbackStub, SM_Str_AssemblyBase_Bool_UInt_RetIntPtr)

DEFINE_CLASS(VECTOR64T, Intrinsics, Vector64`1)
DEFINE_CLASS(VECTOR128T, Intrinsics, Vector128`1)
DEFINE_CLASS(VECTOR256T, Intrinsics, Vector256`1)

#ifndef CROSSGEN_COMPILE
DEFINE_CLASS(VECTORT, Numerics, Vector`1)
#endif // !CROSSGEN_COMPILE

DEFINE_CLASS(MEMBER, Reflection, MemberInfo)


Expand Down
1 change: 1 addition & 0 deletions src/coreclr/src/vm/namespace.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@
#endif // FEATURE_COMINTEROP

#define g_IntrinsicsNS g_RuntimeNS ".Intrinsics"
#define g_NumericsNS g_SystemNS ".Numerics"

#define g_InternalCompilerServicesNS "Internal.Runtime.CompilerServices"
#define g_CompilerServicesNS g_RuntimeNS ".CompilerServices"
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/tests/src/Interop/CMakeLists.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ add_subdirectory(PInvoke/Miscellaneous/HandleRef)
add_subdirectory(PInvoke/Miscellaneous/ThisCall)
add_subdirectory(PInvoke/Miscellaneous/MultipleAssembliesWithSamePInvoke)
add_subdirectory(PInvoke/CriticalHandles)
add_subdirectory(PInvoke/Generics)
add_subdirectory(PInvoke/AsAny)
add_subdirectory(PInvoke/SafeHandles)
add_subdirectory(NativeCallable)
Expand Down
87 changes: 87 additions & 0 deletions src/coreclr/tests/src/Interop/PInvoke/Generics/CMakeLists.txt
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
cmake_minimum_required (VERSION 2.6)
project (GenericsNative)
include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake")
if(CLR_CMAKE_TARGET_ARCH_I386)
add_definitions(-D_TARGET_X86_)
add_definitions(-D_TARGET_XARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_AMD64)
add_definitions(-D_TARGET_AMD64_)
add_definitions(-D_TARGET_XARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_ARM)
add_definitions(-D_TARGET_ARM_)
add_definitions(-D_TARGET_ARMARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_ARM64)
add_definitions(-D_TARGET_ARM64_)
add_definitions(-D_TARGET_ARMARCH_)
endif()
set(SOURCES
GenericsNative.IUnknown.cpp
GenericsNative.NullableB.cpp
GenericsNative.NullableC.cpp
GenericsNative.NullableD.cpp
GenericsNative.NullableF.cpp
GenericsNative.NullableL.cpp
GenericsNative.NullableU.cpp
GenericsNative.Point1B.cpp
GenericsNative.Point1C.cpp
GenericsNative.Point1D.cpp
GenericsNative.Point1F.cpp
GenericsNative.Point1L.cpp
GenericsNative.Point1U.cpp
GenericsNative.Point2B.cpp
GenericsNative.Point2C.cpp
GenericsNative.Point2D.cpp
GenericsNative.Point2F.cpp
GenericsNative.Point2L.cpp
GenericsNative.Point2U.cpp
GenericsNative.Point3B.cpp
GenericsNative.Point3C.cpp
GenericsNative.Point3D.cpp
GenericsNative.Point3F.cpp
GenericsNative.Point3L.cpp
GenericsNative.Point3U.cpp
GenericsNative.Point4B.cpp
GenericsNative.Point4C.cpp
GenericsNative.Point4D.cpp
GenericsNative.Point4F.cpp
GenericsNative.Point4L.cpp
GenericsNative.Point4U.cpp
GenericsNative.SequentialClassB.cpp
GenericsNative.SequentialClassC.cpp
GenericsNative.SequentialClassD.cpp
GenericsNative.SequentialClassF.cpp
GenericsNative.SequentialClassL.cpp
GenericsNative.SequentialClassU.cpp
GenericsNative.SpanB.cpp
GenericsNative.SpanC.cpp
GenericsNative.SpanD.cpp
GenericsNative.SpanF.cpp
GenericsNative.SpanL.cpp
GenericsNative.SpanU.cpp
GenericsNative.Vector64B.cpp
GenericsNative.Vector64C.cpp
GenericsNative.Vector64D.cpp
GenericsNative.Vector64F.cpp
GenericsNative.Vector64L.cpp
GenericsNative.Vector64U.cpp
GenericsNative.Vector128B.cpp
GenericsNative.Vector128C.cpp
GenericsNative.Vector128D.cpp
GenericsNative.Vector128F.cpp
GenericsNative.Vector128L.cpp
GenericsNative.Vector128U.cpp
GenericsNative.Vector256B.cpp
GenericsNative.Vector256C.cpp
GenericsNative.Vector256D.cpp
GenericsNative.Vector256F.cpp
GenericsNative.Vector256L.cpp
GenericsNative.Vector256U.cpp
GenericsNative.VectorB.cpp
GenericsNative.VectorC.cpp
GenericsNative.VectorD.cpp
GenericsNative.VectorF.cpp
GenericsNative.VectorL.cpp
GenericsNative.VectorU.cpp
)
add_library (GenericsNative SHARED ${SOURCES})
install (TARGETS GenericsNative DESTINATION bin)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

extern "C" DLL_EXPORT IUnknown* STDMETHODCALLTYPE GetIComInterface()
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetIComInterfaceOut(IUnknown** pValue)
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT const IUnknown** STDMETHODCALLTYPE GetIComInterfacePtr()
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetIComInterfaces(IUnknown** pValues, int count)
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableB
{
bool hasValue;
bool value;
};

static NullableB NullableBValue = { };

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE GetNullableB(bool hasValue, bool value)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableBOut(bool hasValue, bool value, NullableB* pValue)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableB* STDMETHODCALLTYPE GetNullableBPtr(bool hasValue, bool value)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE AddNullableB(NullableB lhs, NullableB rhs)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE AddNullableBs(const NullableB* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableC
{
bool hasValue;
char16_t value;
};

static NullableC NullableCValue = { };

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE GetNullableC(bool hasValue, char16_t value)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableCOut(bool hasValue, char16_t value, NullableC* pValue)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableC* STDMETHODCALLTYPE GetNullableCPtr(bool hasValue, char16_t value)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE AddNullableC(NullableC lhs, NullableC rhs)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE AddNullableCs(const NullableC* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Doundation under one or more agreements.
// The .NET Doundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableD
{
bool hasValue;
double value;
};

static NullableD NullableDValue = { };

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE GetNullableD(bool hasValue, double value)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableDOut(bool hasValue, double value, NullableD* pValue)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableD* STDMETHODCALLTYPE GetNullableDPtr(bool hasValue, double value)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE AddNullableD(NullableD lhs, NullableD rhs)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE AddNullableDs(const NullableD* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/src/dlls/mscorrc/mscorrc.rc
Original file line numberDiff line numberDiff line change
Expand Up@@ -627,7 +627,7 @@ BEGIN
IDS_EE_BADMARSHAL_NOTMARSHALABLE "The type definition of this field has layout information but has an invalid managed/unmanaged type combination or is unmarshalable."
IDS_EE_BADMARSHAL_BADMETADATA "Invalid marshaling metadata."
IDS_EE_BADMARSHAL_CUSTOMMARSHALER "Custom marshalers are only allowed on classes, strings, arrays, and boxed value types."
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Generic types cannot be marshaled."
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Non-blittable generic types cannot be marshaled."
IDS_EE_BADMARSHAL_STRING_OUT "Cannot marshal a string by-value with the [Out] attribute."

IDS_EE_BADMARSHALPARAM_STRINGBUILDER "Invalid managed/unmanaged type combination (StringBuilders must be paired with LPStr, LPWStr, or LPTStr)."
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -334,13 +334,29 @@ internal static MarshallerKind GetMarshallerKind(
return MarshallerKind.Invalid;
}

if (type.HasInstantiation)
bool isBlittable = MarshalUtils.IsBlittableType(type);

// Blittable generics are allowed to be marshalled with the following exceptions:
// * ByReference<T>: This represents an interior pointer and is not actually blittable
// * Nullable<T>: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
// * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios

if (type.HasInstantiation && (!isBlittable
|| InteropTypes.IsSystemByReference(context, type)
|| InteropTypes.IsSystemNullable(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector64T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector128T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector256T(context, type)
|| InteropTypes.IsSystemNumericsVectorT(context, type)))
{
// Generic types cannot be marshaled.
return MarshallerKind.Invalid;
}

if (MarshalUtils.IsBlittableType(type))
if (isBlittable)
{
if (nativeType != NativeTypeKind.Default && nativeType != NativeTypeKind.Struct)
return MarshallerKind.Invalid;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -108,6 +108,36 @@ public static bool IsSystemArgIterator(TypeSystemContext context, TypeDesc type)
return IsCoreNamedType(context, type, "System", "ArgIterator");
}

public static bool IsSystemByReference(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "ByReference`1");
}

public static bool IsSystemNullable(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "Nullable`1");
}

public static bool IsSystemRuntimeIntrinsicsVector64T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector64`1");
}

public static bool IsSystemRuntimeIntrinsicsVector128T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector128`1");
}

public static bool IsSystemRuntimeIntrinsicsVector256T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector256`1");
}

public static bool IsSystemNumericsVectorT(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Numerics", "Vector`1");
}

private static bool IsOrDerivesFromType(TypeDesc type, MetadataType targetType)
{
while (type != null)
Expand Down
22 changes: 20 additions & 2 deletions src/coreclr/src/vm/mlinfo.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -2796,7 +2796,25 @@ MarshalInfo::MarshalInfo(Module* pModule,
}
#endif // FEATURE_COMINTEROP

if (m_pMT->HasInstantiation())
// Blittable generics are allowed to be marshalled with the following exceptions:
// * ByReference<T>: This represents an interior pointer and is not actually blittable
// * Nullable<T>: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
// * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios

if (m_pMT->HasInstantiation() && (!m_pMT->IsBlittable()
|| m_pMT->HasSameTypeDefAs(g_pByReferenceClass)
|| m_pMT->HasSameTypeDefAs(g_pNullableClass)
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR64T))
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR128T))
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR256T))
#ifndef CROSSGEN_COMPILE
// Crossgen scenarios block Vector<T> from even being loaded
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTORT))
#endif // !CROSSGEN_COMPILE
))
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
Expand DownExpand Up@@ -2916,7 +2934,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
if (m_ms != MARSHAL_SCENARIO_WINRT)
#endif // FEATURE_COMINTEROP
{
if (thElement.HasInstantiation())
if (thElement.HasInstantiation() && !thElement.IsBlittable())
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/src/vm/mscorlib.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -499,6 +499,14 @@ DEFINE_FIELD(MARSHAL, SYSTEM_MAX_DBCS_CHAR_SIZE, SystemMax
DEFINE_CLASS(NATIVELIBRARY, Interop, NativeLibrary)
DEFINE_METHOD(NATIVELIBRARY, LOADLIBRARYCALLBACKSTUB, LoadLibraryCallbackStub, SM_Str_AssemblyBase_Bool_UInt_RetIntPtr)

DEFINE_CLASS(VECTOR64T, Intrinsics, Vector64`1)
DEFINE_CLASS(VECTOR128T, Intrinsics, Vector128`1)
DEFINE_CLASS(VECTOR256T, Intrinsics, Vector256`1)

#ifndef CROSSGEN_COMPILE
DEFINE_CLASS(VECTORT, Numerics, Vector`1)
#endif // !CROSSGEN_COMPILE

DEFINE_CLASS(MEMBER, Reflection, MemberInfo)


Expand Down
1 change: 1 addition & 0 deletions src/coreclr/src/vm/namespace.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@
#endif // FEATURE_COMINTEROP

#define g_IntrinsicsNS g_RuntimeNS ".Intrinsics"
#define g_NumericsNS g_SystemNS ".Numerics"

#define g_InternalCompilerServicesNS "Internal.Runtime.CompilerServices"
#define g_CompilerServicesNS g_RuntimeNS ".CompilerServices"
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/tests/src/Interop/CMakeLists.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ add_subdirectory(PInvoke/Miscellaneous/HandleRef)
add_subdirectory(PInvoke/Miscellaneous/ThisCall)
add_subdirectory(PInvoke/Miscellaneous/MultipleAssembliesWithSamePInvoke)
add_subdirectory(PInvoke/CriticalHandles)
add_subdirectory(PInvoke/Generics)
add_subdirectory(PInvoke/AsAny)
add_subdirectory(PInvoke/SafeHandles)
add_subdirectory(NativeCallable)
Expand Down
87 changes: 87 additions & 0 deletions src/coreclr/tests/src/Interop/PInvoke/Generics/CMakeLists.txt
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
cmake_minimum_required (VERSION 2.6)
project (GenericsNative)
include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake")
if(CLR_CMAKE_TARGET_ARCH_I386)
add_definitions(-D_TARGET_X86_)
add_definitions(-D_TARGET_XARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_AMD64)
add_definitions(-D_TARGET_AMD64_)
add_definitions(-D_TARGET_XARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_ARM)
add_definitions(-D_TARGET_ARM_)
add_definitions(-D_TARGET_ARMARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_ARM64)
add_definitions(-D_TARGET_ARM64_)
add_definitions(-D_TARGET_ARMARCH_)
endif()
set(SOURCES
GenericsNative.IUnknown.cpp
GenericsNative.NullableB.cpp
GenericsNative.NullableC.cpp
GenericsNative.NullableD.cpp
GenericsNative.NullableF.cpp
GenericsNative.NullableL.cpp
GenericsNative.NullableU.cpp
GenericsNative.Point1B.cpp
GenericsNative.Point1C.cpp
GenericsNative.Point1D.cpp
GenericsNative.Point1F.cpp
GenericsNative.Point1L.cpp
GenericsNative.Point1U.cpp
GenericsNative.Point2B.cpp
GenericsNative.Point2C.cpp
GenericsNative.Point2D.cpp
GenericsNative.Point2F.cpp
GenericsNative.Point2L.cpp
GenericsNative.Point2U.cpp
GenericsNative.Point3B.cpp
GenericsNative.Point3C.cpp
GenericsNative.Point3D.cpp
GenericsNative.Point3F.cpp
GenericsNative.Point3L.cpp
GenericsNative.Point3U.cpp
GenericsNative.Point4B.cpp
GenericsNative.Point4C.cpp
GenericsNative.Point4D.cpp
GenericsNative.Point4F.cpp
GenericsNative.Point4L.cpp
GenericsNative.Point4U.cpp
GenericsNative.SequentialClassB.cpp
GenericsNative.SequentialClassC.cpp
GenericsNative.SequentialClassD.cpp
GenericsNative.SequentialClassF.cpp
GenericsNative.SequentialClassL.cpp
GenericsNative.SequentialClassU.cpp
GenericsNative.SpanB.cpp
GenericsNative.SpanC.cpp
GenericsNative.SpanD.cpp
GenericsNative.SpanF.cpp
GenericsNative.SpanL.cpp
GenericsNative.SpanU.cpp
GenericsNative.Vector64B.cpp
GenericsNative.Vector64C.cpp
GenericsNative.Vector64D.cpp
GenericsNative.Vector64F.cpp
GenericsNative.Vector64L.cpp
GenericsNative.Vector64U.cpp
GenericsNative.Vector128B.cpp
GenericsNative.Vector128C.cpp
GenericsNative.Vector128D.cpp
GenericsNative.Vector128F.cpp
GenericsNative.Vector128L.cpp
GenericsNative.Vector128U.cpp
GenericsNative.Vector256B.cpp
GenericsNative.Vector256C.cpp
GenericsNative.Vector256D.cpp
GenericsNative.Vector256F.cpp
GenericsNative.Vector256L.cpp
GenericsNative.Vector256U.cpp
GenericsNative.VectorB.cpp
GenericsNative.VectorC.cpp
GenericsNative.VectorD.cpp
GenericsNative.VectorF.cpp
GenericsNative.VectorL.cpp
GenericsNative.VectorU.cpp
)
add_library (GenericsNative SHARED ${SOURCES})
install (TARGETS GenericsNative DESTINATION bin)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

extern "C" DLL_EXPORT IUnknown* STDMETHODCALLTYPE GetIComInterface()
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetIComInterfaceOut(IUnknown** pValue)
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT const IUnknown** STDMETHODCALLTYPE GetIComInterfacePtr()
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetIComInterfaces(IUnknown** pValues, int count)
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableB
{
bool hasValue;
bool value;
};

static NullableB NullableBValue = { };

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE GetNullableB(bool hasValue, bool value)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableBOut(bool hasValue, bool value, NullableB* pValue)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableB* STDMETHODCALLTYPE GetNullableBPtr(bool hasValue, bool value)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE AddNullableB(NullableB lhs, NullableB rhs)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE AddNullableBs(const NullableB* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableC
{
bool hasValue;
char16_t value;
};

static NullableC NullableCValue = { };

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE GetNullableC(bool hasValue, char16_t value)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableCOut(bool hasValue, char16_t value, NullableC* pValue)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableC* STDMETHODCALLTYPE GetNullableCPtr(bool hasValue, char16_t value)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE AddNullableC(NullableC lhs, NullableC rhs)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE AddNullableCs(const NullableC* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Doundation under one or more agreements.
// The .NET Doundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableD
{
bool hasValue;
double value;
};

static NullableD NullableDValue = { };

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE GetNullableD(bool hasValue, double value)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableDOut(bool hasValue, double value, NullableD* pValue)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableD* STDMETHODCALLTYPE GetNullableDPtr(bool hasValue, double value)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE AddNullableD(NullableD lhs, NullableD rhs)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE AddNullableDs(const NullableD* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/src/dlls/mscorrc/mscorrc.rc
Original file line numberDiff line numberDiff line change
Expand Up@@ -627,7 +627,7 @@ BEGIN
IDS_EE_BADMARSHAL_NOTMARSHALABLE "The type definition of this field has layout information but has an invalid managed/unmanaged type combination or is unmarshalable."
IDS_EE_BADMARSHAL_BADMETADATA "Invalid marshaling metadata."
IDS_EE_BADMARSHAL_CUSTOMMARSHALER "Custom marshalers are only allowed on classes, strings, arrays, and boxed value types."
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Generic types cannot be marshaled."
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Non-blittable generic types cannot be marshaled."
IDS_EE_BADMARSHAL_STRING_OUT "Cannot marshal a string by-value with the [Out] attribute."

IDS_EE_BADMARSHALPARAM_STRINGBUILDER "Invalid managed/unmanaged type combination (StringBuilders must be paired with LPStr, LPWStr, or LPTStr)."
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -334,13 +334,29 @@ internal static MarshallerKind GetMarshallerKind(
return MarshallerKind.Invalid;
}

if (type.HasInstantiation)
bool isBlittable = MarshalUtils.IsBlittableType(type);

// Blittable generics are allowed to be marshalled with the following exceptions:
// * ByReference<T>: This represents an interior pointer and is not actually blittable
// * Nullable<T>: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
// * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios

if (type.HasInstantiation && (!isBlittable
|| InteropTypes.IsSystemByReference(context, type)
|| InteropTypes.IsSystemNullable(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector64T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector128T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector256T(context, type)
|| InteropTypes.IsSystemNumericsVectorT(context, type)))
{
// Generic types cannot be marshaled.
return MarshallerKind.Invalid;
}

if (MarshalUtils.IsBlittableType(type))
if (isBlittable)
{
if (nativeType != NativeTypeKind.Default && nativeType != NativeTypeKind.Struct)
return MarshallerKind.Invalid;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -108,6 +108,36 @@ public static bool IsSystemArgIterator(TypeSystemContext context, TypeDesc type)
return IsCoreNamedType(context, type, "System", "ArgIterator");
}

public static bool IsSystemByReference(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "ByReference`1");
}

public static bool IsSystemNullable(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "Nullable`1");
}

public static bool IsSystemRuntimeIntrinsicsVector64T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector64`1");
}

public static bool IsSystemRuntimeIntrinsicsVector128T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector128`1");
}

public static bool IsSystemRuntimeIntrinsicsVector256T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector256`1");
}

public static bool IsSystemNumericsVectorT(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Numerics", "Vector`1");
}

private static bool IsOrDerivesFromType(TypeDesc type, MetadataType targetType)
{
while (type != null)
Expand Down
22 changes: 20 additions & 2 deletions src/coreclr/src/vm/mlinfo.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -2796,7 +2796,25 @@ MarshalInfo::MarshalInfo(Module* pModule,
}
#endif // FEATURE_COMINTEROP

if (m_pMT->HasInstantiation())
// Blittable generics are allowed to be marshalled with the following exceptions:
// * ByReference<T>: This represents an interior pointer and is not actually blittable
// * Nullable<T>: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
// * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios

if (m_pMT->HasInstantiation() && (!m_pMT->IsBlittable()
|| m_pMT->HasSameTypeDefAs(g_pByReferenceClass)
|| m_pMT->HasSameTypeDefAs(g_pNullableClass)
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR64T))
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR128T))
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR256T))
#ifndef CROSSGEN_COMPILE
// Crossgen scenarios block Vector<T> from even being loaded
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTORT))
#endif // !CROSSGEN_COMPILE
))
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
Expand DownExpand Up@@ -2916,7 +2934,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
if (m_ms != MARSHAL_SCENARIO_WINRT)
#endif // FEATURE_COMINTEROP
{
if (thElement.HasInstantiation())
if (thElement.HasInstantiation() && !thElement.IsBlittable())
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/src/vm/mscorlib.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -499,6 +499,14 @@ DEFINE_FIELD(MARSHAL, SYSTEM_MAX_DBCS_CHAR_SIZE, SystemMax
DEFINE_CLASS(NATIVELIBRARY, Interop, NativeLibrary)
DEFINE_METHOD(NATIVELIBRARY, LOADLIBRARYCALLBACKSTUB, LoadLibraryCallbackStub, SM_Str_AssemblyBase_Bool_UInt_RetIntPtr)

DEFINE_CLASS(VECTOR64T, Intrinsics, Vector64`1)
DEFINE_CLASS(VECTOR128T, Intrinsics, Vector128`1)
DEFINE_CLASS(VECTOR256T, Intrinsics, Vector256`1)

#ifndef CROSSGEN_COMPILE
DEFINE_CLASS(VECTORT, Numerics, Vector`1)
#endif // !CROSSGEN_COMPILE

DEFINE_CLASS(MEMBER, Reflection, MemberInfo)


Expand Down
1 change: 1 addition & 0 deletions src/coreclr/src/vm/namespace.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@
#endif // FEATURE_COMINTEROP

#define g_IntrinsicsNS g_RuntimeNS ".Intrinsics"
#define g_NumericsNS g_SystemNS ".Numerics"

#define g_InternalCompilerServicesNS "Internal.Runtime.CompilerServices"
#define g_CompilerServicesNS g_RuntimeNS ".CompilerServices"
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/tests/src/Interop/CMakeLists.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ add_subdirectory(PInvoke/Miscellaneous/HandleRef)
add_subdirectory(PInvoke/Miscellaneous/ThisCall)
add_subdirectory(PInvoke/Miscellaneous/MultipleAssembliesWithSamePInvoke)
add_subdirectory(PInvoke/CriticalHandles)
add_subdirectory(PInvoke/Generics)
add_subdirectory(PInvoke/AsAny)
add_subdirectory(PInvoke/SafeHandles)
add_subdirectory(NativeCallable)
Expand Down
87 changes: 87 additions & 0 deletions src/coreclr/tests/src/Interop/PInvoke/Generics/CMakeLists.txt
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
cmake_minimum_required (VERSION 2.6)
project (GenericsNative)
include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake")
if(CLR_CMAKE_TARGET_ARCH_I386)
add_definitions(-D_TARGET_X86_)
add_definitions(-D_TARGET_XARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_AMD64)
add_definitions(-D_TARGET_AMD64_)
add_definitions(-D_TARGET_XARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_ARM)
add_definitions(-D_TARGET_ARM_)
add_definitions(-D_TARGET_ARMARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_ARM64)
add_definitions(-D_TARGET_ARM64_)
add_definitions(-D_TARGET_ARMARCH_)
endif()
set(SOURCES
GenericsNative.IUnknown.cpp
GenericsNative.NullableB.cpp
GenericsNative.NullableC.cpp
GenericsNative.NullableD.cpp
GenericsNative.NullableF.cpp
GenericsNative.NullableL.cpp
GenericsNative.NullableU.cpp
GenericsNative.Point1B.cpp
GenericsNative.Point1C.cpp
GenericsNative.Point1D.cpp
GenericsNative.Point1F.cpp
GenericsNative.Point1L.cpp
GenericsNative.Point1U.cpp
GenericsNative.Point2B.cpp
GenericsNative.Point2C.cpp
GenericsNative.Point2D.cpp
GenericsNative.Point2F.cpp
GenericsNative.Point2L.cpp
GenericsNative.Point2U.cpp
GenericsNative.Point3B.cpp
GenericsNative.Point3C.cpp
GenericsNative.Point3D.cpp
GenericsNative.Point3F.cpp
GenericsNative.Point3L.cpp
GenericsNative.Point3U.cpp
GenericsNative.Point4B.cpp
GenericsNative.Point4C.cpp
GenericsNative.Point4D.cpp
GenericsNative.Point4F.cpp
GenericsNative.Point4L.cpp
GenericsNative.Point4U.cpp
GenericsNative.SequentialClassB.cpp
GenericsNative.SequentialClassC.cpp
GenericsNative.SequentialClassD.cpp
GenericsNative.SequentialClassF.cpp
GenericsNative.SequentialClassL.cpp
GenericsNative.SequentialClassU.cpp
GenericsNative.SpanB.cpp
GenericsNative.SpanC.cpp
GenericsNative.SpanD.cpp
GenericsNative.SpanF.cpp
GenericsNative.SpanL.cpp
GenericsNative.SpanU.cpp
GenericsNative.Vector64B.cpp
GenericsNative.Vector64C.cpp
GenericsNative.Vector64D.cpp
GenericsNative.Vector64F.cpp
GenericsNative.Vector64L.cpp
GenericsNative.Vector64U.cpp
GenericsNative.Vector128B.cpp
GenericsNative.Vector128C.cpp
GenericsNative.Vector128D.cpp
GenericsNative.Vector128F.cpp
GenericsNative.Vector128L.cpp
GenericsNative.Vector128U.cpp
GenericsNative.Vector256B.cpp
GenericsNative.Vector256C.cpp
GenericsNative.Vector256D.cpp
GenericsNative.Vector256F.cpp
GenericsNative.Vector256L.cpp
GenericsNative.Vector256U.cpp
GenericsNative.VectorB.cpp
GenericsNative.VectorC.cpp
GenericsNative.VectorD.cpp
GenericsNative.VectorF.cpp
GenericsNative.VectorL.cpp
GenericsNative.VectorU.cpp
)
add_library (GenericsNative SHARED ${SOURCES})
install (TARGETS GenericsNative DESTINATION bin)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

extern "C" DLL_EXPORT IUnknown* STDMETHODCALLTYPE GetIComInterface()
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetIComInterfaceOut(IUnknown** pValue)
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT const IUnknown** STDMETHODCALLTYPE GetIComInterfacePtr()
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetIComInterfaces(IUnknown** pValues, int count)
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableB
{
bool hasValue;
bool value;
};

static NullableB NullableBValue = { };

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE GetNullableB(bool hasValue, bool value)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableBOut(bool hasValue, bool value, NullableB* pValue)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableB* STDMETHODCALLTYPE GetNullableBPtr(bool hasValue, bool value)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE AddNullableB(NullableB lhs, NullableB rhs)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE AddNullableBs(const NullableB* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableC
{
bool hasValue;
char16_t value;
};

static NullableC NullableCValue = { };

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE GetNullableC(bool hasValue, char16_t value)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableCOut(bool hasValue, char16_t value, NullableC* pValue)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableC* STDMETHODCALLTYPE GetNullableCPtr(bool hasValue, char16_t value)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE AddNullableC(NullableC lhs, NullableC rhs)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE AddNullableCs(const NullableC* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Doundation under one or more agreements.
// The .NET Doundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableD
{
bool hasValue;
double value;
};

static NullableD NullableDValue = { };

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE GetNullableD(bool hasValue, double value)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableDOut(bool hasValue, double value, NullableD* pValue)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableD* STDMETHODCALLTYPE GetNullableDPtr(bool hasValue, double value)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE AddNullableD(NullableD lhs, NullableD rhs)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE AddNullableDs(const NullableD* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/src/dlls/mscorrc/mscorrc.rc
Original file line numberDiff line numberDiff line change
Expand Up@@ -627,7 +627,7 @@ BEGIN
IDS_EE_BADMARSHAL_NOTMARSHALABLE "The type definition of this field has layout information but has an invalid managed/unmanaged type combination or is unmarshalable."
IDS_EE_BADMARSHAL_BADMETADATA "Invalid marshaling metadata."
IDS_EE_BADMARSHAL_CUSTOMMARSHALER "Custom marshalers are only allowed on classes, strings, arrays, and boxed value types."
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Generic types cannot be marshaled."
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Non-blittable generic types cannot be marshaled."
IDS_EE_BADMARSHAL_STRING_OUT "Cannot marshal a string by-value with the [Out] attribute."

IDS_EE_BADMARSHALPARAM_STRINGBUILDER "Invalid managed/unmanaged type combination (StringBuilders must be paired with LPStr, LPWStr, or LPTStr)."
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -334,13 +334,29 @@ internal static MarshallerKind GetMarshallerKind(
return MarshallerKind.Invalid;
}

if (type.HasInstantiation)
bool isBlittable = MarshalUtils.IsBlittableType(type);

// Blittable generics are allowed to be marshalled with the following exceptions:
// * ByReference<T>: This represents an interior pointer and is not actually blittable
// * Nullable<T>: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
// * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios

if (type.HasInstantiation && (!isBlittable
|| InteropTypes.IsSystemByReference(context, type)
|| InteropTypes.IsSystemNullable(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector64T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector128T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector256T(context, type)
|| InteropTypes.IsSystemNumericsVectorT(context, type)))
{
// Generic types cannot be marshaled.
return MarshallerKind.Invalid;
}

if (MarshalUtils.IsBlittableType(type))
if (isBlittable)
{
if (nativeType != NativeTypeKind.Default && nativeType != NativeTypeKind.Struct)
return MarshallerKind.Invalid;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -108,6 +108,36 @@ public static bool IsSystemArgIterator(TypeSystemContext context, TypeDesc type)
return IsCoreNamedType(context, type, "System", "ArgIterator");
}

public static bool IsSystemByReference(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "ByReference`1");
}

public static bool IsSystemNullable(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "Nullable`1");
}

public static bool IsSystemRuntimeIntrinsicsVector64T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector64`1");
}

public static bool IsSystemRuntimeIntrinsicsVector128T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector128`1");
}

public static bool IsSystemRuntimeIntrinsicsVector256T(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector256`1");
}

public static bool IsSystemNumericsVectorT(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System.Numerics", "Vector`1");
}

private static bool IsOrDerivesFromType(TypeDesc type, MetadataType targetType)
{
while (type != null)
Expand Down
22 changes: 20 additions & 2 deletions src/coreclr/src/vm/mlinfo.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -2796,7 +2796,25 @@ MarshalInfo::MarshalInfo(Module* pModule,
}
#endif // FEATURE_COMINTEROP

if (m_pMT->HasInstantiation())
// Blittable generics are allowed to be marshalled with the following exceptions:
// * ByReference<T>: This represents an interior pointer and is not actually blittable
// * Nullable<T>: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
// * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios

if (m_pMT->HasInstantiation() && (!m_pMT->IsBlittable()
|| m_pMT->HasSameTypeDefAs(g_pByReferenceClass)
|| m_pMT->HasSameTypeDefAs(g_pNullableClass)
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR64T))
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR128T))
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR256T))
#ifndef CROSSGEN_COMPILE
// Crossgen scenarios block Vector<T> from even being loaded
|| m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTORT))
#endif // !CROSSGEN_COMPILE
))
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
Expand DownExpand Up@@ -2916,7 +2934,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
if (m_ms != MARSHAL_SCENARIO_WINRT)
#endif // FEATURE_COMINTEROP
{
if (thElement.HasInstantiation())
if (thElement.HasInstantiation() && !thElement.IsBlittable())
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/src/vm/mscorlib.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -499,6 +499,14 @@ DEFINE_FIELD(MARSHAL, SYSTEM_MAX_DBCS_CHAR_SIZE, SystemMax
DEFINE_CLASS(NATIVELIBRARY, Interop, NativeLibrary)
DEFINE_METHOD(NATIVELIBRARY, LOADLIBRARYCALLBACKSTUB, LoadLibraryCallbackStub, SM_Str_AssemblyBase_Bool_UInt_RetIntPtr)

DEFINE_CLASS(VECTOR64T, Intrinsics, Vector64`1)
DEFINE_CLASS(VECTOR128T, Intrinsics, Vector128`1)
DEFINE_CLASS(VECTOR256T, Intrinsics, Vector256`1)

#ifndef CROSSGEN_COMPILE
DEFINE_CLASS(VECTORT, Numerics, Vector`1)
#endif // !CROSSGEN_COMPILE

DEFINE_CLASS(MEMBER, Reflection, MemberInfo)


Expand Down
1 change: 1 addition & 0 deletions src/coreclr/src/vm/namespace.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@
#endif // FEATURE_COMINTEROP

#define g_IntrinsicsNS g_RuntimeNS ".Intrinsics"
#define g_NumericsNS g_SystemNS ".Numerics"

#define g_InternalCompilerServicesNS "Internal.Runtime.CompilerServices"
#define g_CompilerServicesNS g_RuntimeNS ".CompilerServices"
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/tests/src/Interop/CMakeLists.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ add_subdirectory(PInvoke/Miscellaneous/HandleRef)
add_subdirectory(PInvoke/Miscellaneous/ThisCall)
add_subdirectory(PInvoke/Miscellaneous/MultipleAssembliesWithSamePInvoke)
add_subdirectory(PInvoke/CriticalHandles)
add_subdirectory(PInvoke/Generics)
add_subdirectory(PInvoke/AsAny)
add_subdirectory(PInvoke/SafeHandles)
add_subdirectory(NativeCallable)
Expand Down
87 changes: 87 additions & 0 deletions src/coreclr/tests/src/Interop/PInvoke/Generics/CMakeLists.txt
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
cmake_minimum_required (VERSION 2.6)
project (GenericsNative)
include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake")
if(CLR_CMAKE_TARGET_ARCH_I386)
add_definitions(-D_TARGET_X86_)
add_definitions(-D_TARGET_XARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_AMD64)
add_definitions(-D_TARGET_AMD64_)
add_definitions(-D_TARGET_XARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_ARM)
add_definitions(-D_TARGET_ARM_)
add_definitions(-D_TARGET_ARMARCH_)
elseif(CLR_CMAKE_TARGET_ARCH_ARM64)
add_definitions(-D_TARGET_ARM64_)
add_definitions(-D_TARGET_ARMARCH_)
endif()
set(SOURCES
GenericsNative.IUnknown.cpp
GenericsNative.NullableB.cpp
GenericsNative.NullableC.cpp
GenericsNative.NullableD.cpp
GenericsNative.NullableF.cpp
GenericsNative.NullableL.cpp
GenericsNative.NullableU.cpp
GenericsNative.Point1B.cpp
GenericsNative.Point1C.cpp
GenericsNative.Point1D.cpp
GenericsNative.Point1F.cpp
GenericsNative.Point1L.cpp
GenericsNative.Point1U.cpp
GenericsNative.Point2B.cpp
GenericsNative.Point2C.cpp
GenericsNative.Point2D.cpp
GenericsNative.Point2F.cpp
GenericsNative.Point2L.cpp
GenericsNative.Point2U.cpp
GenericsNative.Point3B.cpp
GenericsNative.Point3C.cpp
GenericsNative.Point3D.cpp
GenericsNative.Point3F.cpp
GenericsNative.Point3L.cpp
GenericsNative.Point3U.cpp
GenericsNative.Point4B.cpp
GenericsNative.Point4C.cpp
GenericsNative.Point4D.cpp
GenericsNative.Point4F.cpp
GenericsNative.Point4L.cpp
GenericsNative.Point4U.cpp
GenericsNative.SequentialClassB.cpp
GenericsNative.SequentialClassC.cpp
GenericsNative.SequentialClassD.cpp
GenericsNative.SequentialClassF.cpp
GenericsNative.SequentialClassL.cpp
GenericsNative.SequentialClassU.cpp
GenericsNative.SpanB.cpp
GenericsNative.SpanC.cpp
GenericsNative.SpanD.cpp
GenericsNative.SpanF.cpp
GenericsNative.SpanL.cpp
GenericsNative.SpanU.cpp
GenericsNative.Vector64B.cpp
GenericsNative.Vector64C.cpp
GenericsNative.Vector64D.cpp
GenericsNative.Vector64F.cpp
GenericsNative.Vector64L.cpp
GenericsNative.Vector64U.cpp
GenericsNative.Vector128B.cpp
GenericsNative.Vector128C.cpp
GenericsNative.Vector128D.cpp
GenericsNative.Vector128F.cpp
GenericsNative.Vector128L.cpp
GenericsNative.Vector128U.cpp
GenericsNative.Vector256B.cpp
GenericsNative.Vector256C.cpp
GenericsNative.Vector256D.cpp
GenericsNative.Vector256F.cpp
GenericsNative.Vector256L.cpp
GenericsNative.Vector256U.cpp
GenericsNative.VectorB.cpp
GenericsNative.VectorC.cpp
GenericsNative.VectorD.cpp
GenericsNative.VectorF.cpp
GenericsNative.VectorL.cpp
GenericsNative.VectorU.cpp
)
add_library (GenericsNative SHARED ${SOURCES})
install (TARGETS GenericsNative DESTINATION bin)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

extern "C" DLL_EXPORT IUnknown* STDMETHODCALLTYPE GetIComInterface()
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetIComInterfaceOut(IUnknown** pValue)
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT const IUnknown** STDMETHODCALLTYPE GetIComInterfacePtr()
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetIComInterfaces(IUnknown** pValues, int count)
{
throw "P/Invoke for IComInterface<T> should be unsupported.";
}

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableB
{
bool hasValue;
bool value;
};

static NullableB NullableBValue = { };

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE GetNullableB(bool hasValue, bool value)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableBOut(bool hasValue, bool value, NullableB* pValue)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableB* STDMETHODCALLTYPE GetNullableBPtr(bool hasValue, bool value)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE AddNullableB(NullableB lhs, NullableB rhs)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}

extern "C" DLL_EXPORT NullableB STDMETHODCALLTYPE AddNullableBs(const NullableB* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<bool> should be unsupported.";
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableC
{
bool hasValue;
char16_t value;
};

static NullableC NullableCValue = { };

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE GetNullableC(bool hasValue, char16_t value)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableCOut(bool hasValue, char16_t value, NullableC* pValue)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableC* STDMETHODCALLTYPE GetNullableCPtr(bool hasValue, char16_t value)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE AddNullableC(NullableC lhs, NullableC rhs)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}

extern "C" DLL_EXPORT NullableC STDMETHODCALLTYPE AddNullableCs(const NullableC* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<char> should be unsupported.";
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Doundation under one or more agreements.
// The .NET Doundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <stdio.h>
#include <stdint.h>
#include <xplatform.h>
#include <platformdefines.h>

struct NullableD
{
bool hasValue;
double value;
};

static NullableD NullableDValue = { };

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE GetNullableD(bool hasValue, double value)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetNullableDOut(bool hasValue, double value, NullableD* pValue)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT const NullableD* STDMETHODCALLTYPE GetNullableDPtr(bool hasValue, double value)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE AddNullableD(NullableD lhs, NullableD rhs)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}

extern "C" DLL_EXPORT NullableD STDMETHODCALLTYPE AddNullableDs(const NullableD* pValues, uint32_t count)
{
throw "P/Invoke for Nullable<double> should be unsupported.";
}
Loading