diff --git a/CMake/Modules/FindNF_CoreCLR.cmake b/CMake/Modules/FindNF_CoreCLR.cmake
index 10425d0682..3896adb7f1 100644
--- a/CMake/Modules/FindNF_CoreCLR.cmake
+++ b/CMake/Modules/FindNF_CoreCLR.cmake
@@ -106,11 +106,13 @@ set(NF_CoreCLR_SRCS
corlib_native_System_Number.cpp
corlib_native_System_Object.cpp
corlib_native_System_Random.cpp
+ corlib_native_System_ReadOnlySpan_1.cpp
corlib_native_System_Reflection_Binder.cpp
corlib_native_System_Reflection_MemberInfo.cpp
corlib_native_System_Runtime_CompilerServices_RuntimeHelpers.cpp
corlib_native_System_Runtime_Remoting_RemotingServices.cpp
corlib_native_System_String.cpp
+ corlib_native_System_Span_1.cpp
corlib_native_System_Threading_AutoResetEvent.cpp
corlib_native_System_Threading_Interlocked.cpp
corlib_native_System_Threading_ManualResetEvent.cpp
diff --git a/src/CLR/CorLib/CorLib.vcxproj b/src/CLR/CorLib/CorLib.vcxproj
index 1917a4a142..52ba6cf841 100644
--- a/src/CLR/CorLib/CorLib.vcxproj
+++ b/src/CLR/CorLib/CorLib.vcxproj
@@ -48,6 +48,7 @@
+
@@ -60,6 +61,7 @@
+
@@ -208,4 +210,4 @@
-
+
\ No newline at end of file
diff --git a/src/CLR/CorLib/CorLib.vcxproj.filters b/src/CLR/CorLib/CorLib.vcxproj.filters
index 94b8a4c749..ebb17ab622 100644
--- a/src/CLR/CorLib/CorLib.vcxproj.filters
+++ b/src/CLR/CorLib/CorLib.vcxproj.filters
@@ -173,5 +173,11 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
\ No newline at end of file
diff --git a/src/CLR/CorLib/corlib_native.cpp b/src/CLR/CorLib/corlib_native.cpp
index 79427facfb..41cedd813f 100644
--- a/src/CLR/CorLib/corlib_native.cpp
+++ b/src/CLR/CorLib/corlib_native.cpp
@@ -56,6 +56,7 @@ static const CLR_RT_MethodHandler method_lookup[] =
Library_corlib_native_System_Reflection_FieldInfo::GetCustomAttributesNative___SZARRAY_OBJECT__BOOLEAN,
nullptr,
Library_corlib_native_System_Type::get_DeclaringType___SystemType,
+ Library_corlib_native_System_Type::GetGenericTypeDefinition___SystemType,
nullptr,
nullptr,
nullptr,
@@ -69,6 +70,7 @@ static const CLR_RT_MethodHandler method_lookup[] =
nullptr,
Library_corlib_native_System_Type::IsInstanceOfType___BOOLEAN__OBJECT,
nullptr,
+ Library_corlib_native_System_Type::GetGenericArguments___SZARRAY_SystemType,
Library_corlib_native_System_Type::InvokeMember___OBJECT__STRING__SystemReflectionBindingFlags__SystemReflectionBinder__OBJECT__SZARRAY_OBJECT,
Library_corlib_native_System_Type::GetConstructor___SystemReflectionConstructorInfo__SZARRAY_SystemType,
Library_corlib_native_System_Type::GetConstructors___SZARRAY_SystemReflectionConstructorInfo,
@@ -86,6 +88,8 @@ static const CLR_RT_MethodHandler method_lookup[] =
Library_corlib_native_System_Type::get_IsEnum___BOOLEAN,
Library_corlib_native_System_Type::get_IsSerializable___BOOLEAN,
Library_corlib_native_System_Type::get_IsArray___BOOLEAN,
+ Library_corlib_native_System_Type::get_IsGenericType___BOOLEAN,
+ Library_corlib_native_System_Type::get_IsGenericTypeDefinition___BOOLEAN,
nullptr,
nullptr,
Library_corlib_native_System_Type::GetTypeInternal___STATIC__SystemType__STRING__STRING__BOOLEAN__SZARRAY_I4,
@@ -255,6 +259,7 @@ static const CLR_RT_MethodHandler method_lookup[] =
nullptr,
nullptr,
nullptr,
+ nullptr,
Library_corlib_native_System_Array::TrySzIndexOf___STATIC__BOOLEAN__SystemArray__I4__I4__OBJECT__BYREF_I4,
nullptr,
nullptr,
@@ -269,6 +274,10 @@ static const CLR_RT_MethodHandler method_lookup[] =
nullptr,
nullptr,
nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
Library_corlib_native_System_BitConverter::get_IsLittleEndian___STATIC__BOOLEAN,
Library_corlib_native_System_BitConverter::DoubleToInt64Bits___STATIC__I8__R8,
Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__BOOLEAN,
@@ -524,6 +533,7 @@ static const CLR_RT_MethodHandler method_lookup[] =
Library_corlib_native_System_Reflection_Assembly::LoadInternal___STATIC__SystemReflectionAssembly__STRING__BOOLEAN__I4__I4__I4__I4,
Library_corlib_native_System_Reflection_Assembly::Load___STATIC__SystemReflectionAssembly__SZARRAY_U1,
nullptr,
+ nullptr,
Library_corlib_native_System_Enum::HasFlag___BOOLEAN__SystemEnum,
nullptr,
nullptr,
@@ -625,6 +635,18 @@ static const CLR_RT_MethodHandler method_lookup[] =
nullptr,
nullptr,
nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
Library_corlib_native_System_Number::FormatNative___STATIC__STRING__OBJECT__BOOLEAN__STRING__STRING__STRING__STRING__SZARRAY_I4,
nullptr,
nullptr,
@@ -645,6 +667,16 @@ static const CLR_RT_MethodHandler method_lookup[] =
nullptr,
nullptr,
nullptr,
+ Library_corlib_native_System_ReadOnlySpan_1::NativeReadOnlySpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
Library_corlib_native_System_Reflection_ConstructorInfo::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN,
Library_corlib_native_System_Reflection_ConstructorInfo::Invoke___OBJECT__SZARRAY_OBJECT,
nullptr,
@@ -691,10 +723,12 @@ static const CLR_RT_MethodHandler method_lookup[] =
nullptr,
nullptr,
nullptr,
+ nullptr,
Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers::InitializeArray___STATIC__VOID__SystemArray__SystemRuntimeFieldHandle,
Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers::GetObjectValue___STATIC__OBJECT__OBJECT,
Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers::RunClassConstructor___STATIC__VOID__SystemRuntimeTypeHandle,
Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers::get_OffsetToStringData___STATIC__I4,
+ nullptr,
Library_corlib_native_System_Runtime_Remoting_RemotingServices::IsTransparentProxy___STATIC__BOOLEAN__OBJECT,
nullptr,
nullptr,
@@ -734,6 +768,13 @@ static const CLR_RT_MethodHandler method_lookup[] =
nullptr,
nullptr,
nullptr,
+ Library_corlib_native_System_Span_1::CopyTo___VOID__SystemSpan_1,
+ nullptr,
+ nullptr,
+ nullptr,
+ Library_corlib_native_System_Span_1::NativeSpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4,
+ nullptr,
+ nullptr,
nullptr,
nullptr,
nullptr,
@@ -1507,7 +1548,7 @@ const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib =
#if (NANOCLR_REFLECTION == TRUE)
- 0x50BF350D,
+ 0x17B85422,
#elif (NANOCLR_REFLECTION == FALSE)
diff --git a/src/CLR/CorLib/corlib_native.h b/src/CLR/CorLib/corlib_native.h
index 2fedf785a1..2eb0d33c09 100644
--- a/src/CLR/CorLib/corlib_native.h
+++ b/src/CLR/CorLib/corlib_native.h
@@ -91,8 +91,10 @@ struct Library_corlib_native_System_Reflection_FieldInfo
struct Library_corlib_native_System_Type
{
NANOCLR_NATIVE_DECLARE(get_DeclaringType___SystemType);
+ NANOCLR_NATIVE_DECLARE(GetGenericTypeDefinition___SystemType);
NANOCLR_NATIVE_DECLARE(GetMethod___SystemReflectionMethodInfo__STRING__SystemReflectionBindingFlags);
NANOCLR_NATIVE_DECLARE(IsInstanceOfType___BOOLEAN__OBJECT);
+ NANOCLR_NATIVE_DECLARE(GetGenericArguments___SZARRAY_SystemType);
NANOCLR_NATIVE_DECLARE(
InvokeMember___OBJECT__STRING__SystemReflectionBindingFlags__SystemReflectionBinder__OBJECT__SZARRAY_OBJECT);
NANOCLR_NATIVE_DECLARE(GetConstructor___SystemReflectionConstructorInfo__SZARRAY_SystemType);
@@ -108,6 +110,8 @@ struct Library_corlib_native_System_Type
NANOCLR_NATIVE_DECLARE(get_IsEnum___BOOLEAN);
NANOCLR_NATIVE_DECLARE(get_IsSerializable___BOOLEAN);
NANOCLR_NATIVE_DECLARE(get_IsArray___BOOLEAN);
+ NANOCLR_NATIVE_DECLARE(get_IsGenericType___BOOLEAN);
+ NANOCLR_NATIVE_DECLARE(get_IsGenericTypeDefinition___BOOLEAN);
NANOCLR_NATIVE_DECLARE(GetTypeInternal___STATIC__SystemType__STRING__STRING__BOOLEAN__SZARRAY_I4);
NANOCLR_NATIVE_DECLARE(GetTypeFromHandle___STATIC__SystemType__SystemRuntimeTypeHandle);
@@ -697,6 +701,14 @@ struct Library_corlib_native_System_MulticastDelegate
//--//
};
+struct Library_corlib_native_System_Nullable_1
+{
+ static const int FIELD__hasValue = 1;
+ static const int FIELD__value = 2;
+
+ //--//
+};
+
struct Library_corlib_native_System_Number
{
NANOCLR_NATIVE_DECLARE(FormatNative___STATIC__STRING__OBJECT__BOOLEAN__STRING__STRING__STRING__STRING__SZARRAY_I4);
@@ -764,6 +776,20 @@ struct Library_corlib_native_System_Random
static HRESULT GetRandom(CLR_RT_StackFrame &stack, CLR_RT_Random *&rand, bool create = false);
};
+#if (NANOCLR_REFLECTION == TRUE)
+
+struct Library_corlib_native_System_ReadOnlySpan_1
+{
+ static const int FIELD___array = 1;
+ static const int FIELD___length = 2;
+
+ NANOCLR_NATIVE_DECLARE(NativeReadOnlySpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4);
+
+ //--//
+};
+
+#endif // NANOCLR_REFLECTION
+
struct Library_corlib_native_System_Reflection_AssemblyName
{
static const int FIELD___assembly = 1;
@@ -910,6 +936,23 @@ struct Library_corlib_native_System_Single
//--//
};
+#if (NANOCLR_REFLECTION == TRUE)
+
+struct Library_corlib_native_System_Span_1
+{
+ static const int FIELD___array = 1;
+ static const int FIELD___length = 2;
+
+ NANOCLR_NATIVE_DECLARE(CopyTo___VOID__SystemSpan_1);
+ NANOCLR_NATIVE_DECLARE(NativeSpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4);
+
+ //--//
+};
+
+#endif // NANOCLR_REFLECTION
+
+#if (NANOCLR_REFLECTION != TRUE)
+
struct Library_corlib_native_System_SpanByte
{
static const int FIELD___array = 1;
@@ -919,6 +962,8 @@ struct Library_corlib_native_System_SpanByte
//--//
};
+#endif // NANOCLR_REFLECTION
+
struct Library_corlib_native_System_Threading_AutoResetEvent
{
NANOCLR_NATIVE_DECLARE(_ctor___VOID__BOOLEAN);
diff --git a/src/CLR/CorLib/corlib_native_System_ReadOnlySpan_1.cpp b/src/CLR/CorLib/corlib_native_System_ReadOnlySpan_1.cpp
new file mode 100644
index 0000000000..b3dcd53119
--- /dev/null
+++ b/src/CLR/CorLib/corlib_native_System_ReadOnlySpan_1.cpp
@@ -0,0 +1,52 @@
+//
+// Copyright (c) .NET Foundation and Contributors
+// Portions Copyright (c) Microsoft Corporation. All rights reserved.
+// See LICENSE file in the project root for full license information.
+//
+
+#include "CorLib.h"
+
+HRESULT Library_corlib_native_System_ReadOnlySpan_1::NativeReadOnlySpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4(
+ CLR_RT_StackFrame &stack)
+{
+ NANOCLR_HEADER();
+
+ int32_t start;
+ int32_t length;
+
+ CLR_RT_TypeDescriptor descDst{};
+ CLR_RT_TypeDef_Index sourceType{};
+ CLR_RT_HeapBlock_Array *destinationArray;
+ CLR_RT_HeapBlock_Array *sourceArray = stack.Arg1().DereferenceArray();
+ CLR_RT_HeapBlock *thisSpan = stack.This();
+
+ // get working values
+ start = stack.Arg2().NumericByRefConst().s4;
+ length = stack.Arg3().NumericByRefConst().s4;
+
+ {
+ // get type of the source array
+ NANOCLR_CHECK_HRESULT(descDst.InitializeFromObject(*sourceArray));
+ descDst.GetElementType(descDst);
+
+ sourceType.data = descDst.m_handlerCls.data;
+
+ CLR_RT_HeapBlock &refArray = thisSpan[FIELD___array];
+ CLR_RT_HeapBlock_Array::CreateInstance(refArray, length, sourceType);
+
+ // get pointer to the array
+ destinationArray = thisSpan[FIELD___array].DereferenceArray();
+
+ // protect from GC
+ CLR_RT_ProtectFromGC gc1(*sourceArray);
+ CLR_RT_ProtectFromGC gc2(refArray);
+
+ // copy array
+ CLR_RT_HeapBlock_Array::Copy(sourceArray, start, destinationArray, 0, length);
+
+ // set length
+ thisSpan[FIELD___length].NumericByRef().s4 = length;
+ }
+
+ NANOCLR_NOCLEANUP();
+}
diff --git a/src/CLR/CorLib/corlib_native_System_Span_1.cpp b/src/CLR/CorLib/corlib_native_System_Span_1.cpp
new file mode 100644
index 0000000000..e9cebde926
--- /dev/null
+++ b/src/CLR/CorLib/corlib_native_System_Span_1.cpp
@@ -0,0 +1,98 @@
+//
+// Copyright (c) .NET Foundation and Contributors
+// Portions Copyright (c) Microsoft Corporation. All rights reserved.
+// See LICENSE file in the project root for full license information.
+//
+
+#include "CorLib.h"
+
+HRESULT Library_corlib_native_System_Span_1::CopyTo___VOID__SystemSpan_1(CLR_RT_StackFrame &stack)
+{
+ NANOCLR_HEADER();
+
+ CLR_RT_HeapBlock_Array *sourceArray;
+ CLR_RT_HeapBlock_Array *destinationArray;
+ CLR_RT_HeapBlock *sourceSpan = stack.This();
+ CLR_RT_HeapBlock *destinationSpan = stack.Arg1().Dereference();
+
+ // check lengths
+ if (sourceSpan[FIELD___length].NumericByRefConst().u4 > destinationSpan[FIELD___length].NumericByRefConst().u4)
+ {
+ NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
+ }
+
+ // get pointers to the arrays
+ sourceArray = sourceSpan[FIELD___array].DereferenceArray();
+ destinationArray = destinationSpan[FIELD___array].DereferenceArray();
+
+ {
+ // prevent GC from moving the arrays while we copy the data
+ if (sourceArray)
+ {
+ CLR_RT_ProtectFromGC gc1(*sourceArray);
+ }
+ if (destinationArray)
+ {
+ CLR_RT_ProtectFromGC gc2(*destinationArray);
+ }
+
+ // does the source array has a reference?
+ if (sourceArray && destinationArray)
+ {
+ // copy array
+ CLR_RT_HeapBlock_Array::Copy(
+ sourceArray,
+ 0,
+ destinationArray,
+ 0,
+ sourceSpan[FIELD___length].NumericByRefConst().s4);
+ }
+ }
+
+ NANOCLR_NOCLEANUP();
+}
+
+HRESULT Library_corlib_native_System_Span_1::NativeSpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4(
+ CLR_RT_StackFrame &stack)
+{
+ NANOCLR_HEADER();
+
+ int32_t start;
+ int32_t length;
+
+ CLR_RT_TypeDescriptor descDst{};
+ CLR_RT_TypeDef_Index sourceType{};
+ CLR_RT_HeapBlock_Array *destinationArray;
+ CLR_RT_HeapBlock_Array *sourceArray = stack.Arg1().DereferenceArray();
+ CLR_RT_HeapBlock *thisSpan = stack.This();
+
+ // get working values
+ start = stack.Arg2().NumericByRefConst().s4;
+ length = stack.Arg3().NumericByRefConst().s4;
+
+ {
+ // get type of the source array
+ NANOCLR_CHECK_HRESULT(descDst.InitializeFromObject(*sourceArray));
+ descDst.GetElementType(descDst);
+
+ sourceType.data = descDst.m_handlerCls.data;
+
+ CLR_RT_HeapBlock &refArray = thisSpan[FIELD___array];
+ CLR_RT_HeapBlock_Array::CreateInstance(refArray, length, sourceType);
+
+ // get pointer to the array
+ destinationArray = thisSpan[FIELD___array].DereferenceArray();
+
+ // protect from GC
+ CLR_RT_ProtectFromGC gc1(*sourceArray);
+ CLR_RT_ProtectFromGC gc2(refArray);
+
+ // copy array
+ CLR_RT_HeapBlock_Array::Copy(sourceArray, start, destinationArray, 0, length);
+
+ // set length
+ thisSpan[FIELD___length].NumericByRef().s4 = length;
+ }
+
+ NANOCLR_NOCLEANUP();
+}
diff --git a/src/CLR/CorLib/corlib_native_System_Type.cpp b/src/CLR/CorLib/corlib_native_System_Type.cpp
index 2263f6fe02..14a6a5d1a7 100644
--- a/src/CLR/CorLib/corlib_native_System_Type.cpp
+++ b/src/CLR/CorLib/corlib_native_System_Type.cpp
@@ -32,6 +32,48 @@ HRESULT Library_corlib_native_System_Type::get_DeclaringType___SystemType(CLR_RT
NANOCLR_NOCLEANUP();
}
+HRESULT Library_corlib_native_System_Type::GetGenericTypeDefinition___SystemType(CLR_RT_StackFrame &stack)
+{
+ NATIVE_PROFILE_CLR_CORE();
+ NANOCLR_HEADER();
+
+ CLR_RT_TypeDescriptor desc{};
+ CLR_RT_TypeSpec_Instance genericInstance = {};
+
+ CLR_RT_HeapBlock &top = stack.PushValueAndClear();
+
+ // build a TypeDescriptor from "this"
+ CLR_RT_HeapBlock *hbType = stack.This();
+
+ NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.TypeStatic));
+
+ if (hbType->ReflectionDataConst().kind == CLR_ReflectionType::REFLECTION_TYPESPEC)
+ {
+ // instanciate the generic type
+ genericInstance.InitializeFromIndex(hbType->ObjectGenericType());
+
+ CLR_RT_SignatureParser parser;
+ parser.Initialize_TypeSpec(genericInstance);
+
+ CLR_RT_SignatureParser::Element element;
+
+ // consume GENERICINST
+ parser.Advance(element);
+
+ // consume class | value type
+ parser.Advance(element);
+
+ top.Dereference()->SetReflection(element.Class);
+ }
+ else
+ {
+ NANOCLR_CHECK_HRESULT(desc.InitializeFromReflection(hbType->ReflectionDataConst()));
+ top.Dereference()->SetReflection(desc.m_handlerCls);
+ }
+
+ NANOCLR_NOCLEANUP();
+}
+
HRESULT Library_corlib_native_System_Type::GetMethod___SystemReflectionMethodInfo__STRING__SystemReflectionBindingFlags(
CLR_RT_StackFrame &stack)
{
@@ -66,6 +108,67 @@ HRESULT Library_corlib_native_System_Type::IsInstanceOfType___BOOLEAN__OBJECT(CL
NANOCLR_NOCLEANUP();
}
+HRESULT Library_corlib_native_System_Type::GetGenericArguments___SZARRAY_SystemType(CLR_RT_StackFrame &stack)
+{
+ NATIVE_PROFILE_CLR_CORE();
+ NANOCLR_HEADER();
+
+ int count;
+
+ CLR_RT_SignatureParser parser{};
+ CLR_RT_SignatureParser::Element elem;
+ CLR_RT_TypeSpec_Instance genericInstance;
+ CLR_RT_HeapBlock *hbType;
+ CLR_RT_HeapBlock *pElems;
+
+ CLR_RT_HeapBlock &top = stack.PushValueAndClear();
+
+ // build a TypeDescriptor from "this"
+ hbType = stack.This();
+
+ // sanity check for type spec instance
+ if (hbType->ReflectionDataConst().kind != CLR_ReflectionType::REFLECTION_TYPESPEC)
+ {
+ NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION);
+ }
+
+ // instanciate the generic type
+ if (genericInstance.InitializeFromIndex(hbType->ObjectGenericType()))
+ {
+ // parse the type spec to get the generic arguments
+ parser.Initialize_TypeSpec(genericInstance);
+
+ // consume GENERICINST
+ NANOCLR_CHECK_HRESULT(parser.Advance(elem));
+
+ // consume class | value type
+ NANOCLR_CHECK_HRESULT(parser.Advance(elem));
+
+ // get the number of generic parameters
+ count = parser.GenParamCount;
+
+ // allocate an array to hold the generic arguments
+ NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(top, count, g_CLR_RT_WellKnownTypes.TypeStatic));
+
+ pElems = (CLR_RT_HeapBlock *)top.DereferenceArray()->GetFirstElement();
+
+ // fill the array with Type objects for each generic argument
+ for (int i = 0; i < count; i++)
+ {
+ NANOCLR_CHECK_HRESULT(parser.Advance(elem));
+
+ CLR_RT_HeapBlock &slot = pElems[i];
+ NANOCLR_CHECK_HRESULT(
+ g_CLR_RT_ExecutionEngine.NewObjectFromIndex(slot, g_CLR_RT_WellKnownTypes.TypeStatic));
+
+ CLR_RT_HeapBlock *hbObj = slot.Dereference();
+ hbObj->SetReflection(elem.Class);
+ }
+ }
+
+ NANOCLR_NOCLEANUP();
+}
+
HRESULT Library_corlib_native_System_Type::
InvokeMember___OBJECT__STRING__SystemReflectionBindingFlags__SystemReflectionBinder__OBJECT__SZARRAY_OBJECT(
CLR_RT_StackFrame &stack)
@@ -251,11 +354,120 @@ HRESULT Library_corlib_native_System_Type::get_IsArray___BOOLEAN(CLR_RT_StackFra
NANOCLR_HEADER();
CLR_RT_TypeDef_Instance td;
+ CLR_RT_TypeSpec_Instance genericInstance = {};
+
CLR_RT_HeapBlock *hbType = stack.This();
- NANOCLR_CHECK_HRESULT(Library_corlib_native_System_RuntimeType::GetTypeDescriptor(*hbType, td));
+ if (hbType->ReflectionDataConst().kind == CLR_ReflectionType::REFLECTION_TYPESPEC)
+ {
+ // instanciate the generic type
+ genericInstance.InitializeFromIndex(hbType->ObjectGenericType());
+
+ CLR_RT_SignatureParser parser{};
+ parser.Initialize_TypeSpec(genericInstance);
+
+ CLR_RT_SignatureParser::Element element;
+
+ // only need to consume the 1st element which has the level data we're looking for
+ parser.Advance(element);
+
+ // check if element has levels
+ stack.SetResult_Boolean(element.Levels > 0);
+ }
+ else
+ {
+ NANOCLR_CHECK_HRESULT(Library_corlib_native_System_RuntimeType::GetTypeDescriptor(*hbType, td));
+
+ stack.SetResult_Boolean(td.data == g_CLR_RT_WellKnownTypes.Array.data);
+ }
+
+ NANOCLR_NOCLEANUP();
+}
+
+HRESULT Library_corlib_native_System_Type::get_IsGenericType___BOOLEAN(CLR_RT_StackFrame &stack)
+{
+ NATIVE_PROFILE_CLR_CORE();
+ NANOCLR_HEADER();
+
+ bool isGenericType;
+ CLR_RT_TypeDescriptor desc{};
+
+ CLR_RT_HeapBlock *hbType = stack.This();
+
+ // turn the boxed System.Type ("this") into a TypeDescriptor
+ NANOCLR_CHECK_HRESULT(desc.InitializeFromReflection(hbType->ReflectionDataConst()));
+
+ // simple check: a generic type has generic parameters
+ isGenericType = (desc.m_handlerCls.target->genericParamCount > 0);
+
+ stack.SetResult_Boolean(isGenericType);
+
+ NANOCLR_NOCLEANUP();
+}
+
+HRESULT Library_corlib_native_System_Type::get_IsGenericTypeDefinition___BOOLEAN(CLR_RT_StackFrame &stack)
+{
+ NANOCLR_HEADER();
+
+ bool isTypeDefinition = false;
+ CLR_RT_TypeDescriptor desc{};
+ CLR_RT_TypeSpec_Instance genericInstance = {};
+
+ CLR_RT_HeapBlock *hbType = stack.This();
+
+ if (hbType->ReflectionDataConst().kind == CLR_ReflectionType::REFLECTION_TYPESPEC)
+ {
+ // instanciate the generic type
+ genericInstance.InitializeFromIndex(hbType->ObjectGenericType());
+
+ CLR_RT_SignatureParser parser;
+ parser.Initialize_TypeSpec(genericInstance);
+
+ CLR_RT_SignatureParser::Element element;
+
+ // consume GENERICINST
+ parser.Advance(element);
+
+ // consume class | value type
+ parser.Advance(element);
+
+ // check if it has generic parameters
+ if (parser.GenParamCount == 0)
+ {
+ isTypeDefinition = false;
+ }
+ else
+ {
+ // keep reading the generic parameters
+ for (int i = 0; i < parser.GenParamCount; i++)
+ {
+ if (SUCCEEDED(parser.Advance(element)))
+ {
+ if (element.DataType == DATATYPE_VAR || element.DataType == DATATYPE_MVAR)
+ {
+ // if we find a VAR or MVAR, then this is a generic type definition
+ isTypeDefinition = true;
+ break;
+ }
+ else
+ {
+ // anything else, this is not a generic type definition
+ isTypeDefinition = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // turn the boxed System.Type ("this") into a TypeDescriptor
+ NANOCLR_CHECK_HRESULT(desc.InitializeFromReflection(hbType->ReflectionDataConst()));
+
+ isTypeDefinition = (desc.m_handlerCls.target->genericParamCount > 0);
+ }
- stack.SetResult_Boolean(td.data == g_CLR_RT_WellKnownTypes.Array.data);
+ stack.SetResult_Boolean(isTypeDefinition);
NANOCLR_NOCLEANUP();
}
diff --git a/src/CLR/Core/CLR_RT_HeapBlock.cpp b/src/CLR/Core/CLR_RT_HeapBlock.cpp
index 6bcf07ab0a..98b3572682 100644
--- a/src/CLR/Core/CLR_RT_HeapBlock.cpp
+++ b/src/CLR/Core/CLR_RT_HeapBlock.cpp
@@ -232,56 +232,17 @@ HRESULT CLR_RT_HeapBlock::SetReflection(const CLR_RT_Assembly_Index &assm)
NANOCLR_NOCLEANUP_NOLABEL();
}
-HRESULT CLR_RT_HeapBlock::SetReflection(const CLR_RT_TypeSpec_Instance &tsInst, const CLR_RT_TypeSpec_Index *caller)
+HRESULT CLR_RT_HeapBlock::SetReflection(const CLR_RT_TypeSpec_Index &typeSpec)
{
NATIVE_PROFILE_CLR_CORE();
NANOCLR_HEADER();
m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_REFLECTION, 0, 1);
- m_data.reflection.kind = REFLECTION_TYPE;
-
- // start parsing the signature
- CLR_RT_SignatureParser parser;
- parser.Initialize_TypeSpec(tsInst.assembly, tsInst.target);
-
- // read first element
- CLR_RT_SignatureParser::Element elem;
- if (FAILED(parser.Advance(elem)))
- {
- NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
- }
-
- if (elem.DataType == DATATYPE_VAR || elem.DataType == DATATYPE_MVAR)
- {
- int gpIndex = elem.GenericParamPosition;
-
- // if the caller's genericType is non‐null, ask the CLR to map !n→actual argument:
- if (caller != nullptr && NANOCLR_INDEX_IS_VALID(*caller))
- {
- CLR_RT_TypeDef_Index tdArg{};
- NanoCLRDataType dtArg;
-
- bool ok = g_CLR_RT_TypeSystem.m_assemblies[caller->Assembly() - 1]
- ->FindGenericParamAtTypeSpec(caller->TypeSpec(), gpIndex, tdArg, dtArg);
- if (ok)
- {
- m_data.reflection.data.type = tdArg;
- m_data.reflection.levels = elem.Levels;
- }
- }
- else
- {
- // TODO
- _ASSERTE(false);
- }
- }
- else
- {
- m_data.reflection.data.type = elem.Class;
- m_data.reflection.levels = elem.Levels;
- }
+ m_data.reflection.kind = REFLECTION_TYPESPEC;
+ m_data.reflection.levels = 0;
+ m_data.reflection.data.typeSpec = typeSpec;
- NANOCLR_NOCLEANUP();
+ NANOCLR_NOCLEANUP_NOLABEL();
}
HRESULT CLR_RT_HeapBlock::SetReflection(const CLR_RT_TypeDef_Index &cls)
@@ -349,23 +310,14 @@ HRESULT CLR_RT_HeapBlock::SetObjectCls(const CLR_RT_TypeDef_Index &cls)
NANOCLR_NOCLEANUP();
}
-HRESULT CLR_RT_HeapBlock::SetGenericInstanceObject(const CLR_RT_TypeSpec_Index &genericType)
+HRESULT CLR_RT_HeapBlock::SetGenericInstanceType(const CLR_RT_TypeSpec_Index &genericType)
{
NATIVE_PROFILE_CLR_CORE();
NANOCLR_HEADER();
- CLR_RT_TypeSpec_Instance instance;
+ m_data.reflection.data.typeSpec = genericType;
- if (instance.InitializeFromIndex(genericType) == false)
- {
- NANOCLR_SET_AND_LEAVE(CLR_E_FAIL);
- }
-
- m_data.genericInstance.genericType = genericType;
- m_data.genericInstance.ptr = nullptr;
- m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_GENERICINST, 0, 1);
-
- NANOCLR_NOCLEANUP();
+ NANOCLR_NOCLEANUP_NOLABEL();
}
//--//
@@ -850,7 +802,7 @@ bool CLR_RT_HeapBlock::TypeDescriptorsMatch(
auto &eSpec = expectedType.m_handlerGenericType;
auto &aSpec = actualType.m_handlerGenericType;
- return eSpec.Assembly() == aSpec.Assembly() && eSpec.typeDefIndex == aSpec.typeDefIndex;
+ return eSpec.Assembly() == aSpec.Assembly() && eSpec.genericTypeDef.data == aSpec.genericTypeDef.data;
}
if (actualDataType <= DATATYPE_LAST_PRIMITIVE_TO_PRESERVE)
@@ -1097,7 +1049,7 @@ HRESULT CLR_RT_HeapBlock::PerformUnboxing(const CLR_RT_TypeDef_Instance &cls)
// Validates that src keeps something boxed and the boxed value is VALUE type.
if (src->IsBoxed() == false || src->DataType() != DATATYPE_VALUETYPE)
{
- NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
+ NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST);
}
// Validates the type of data kept by object corresponds to type in cls.
diff --git a/src/CLR/Core/CLR_RT_HeapBlock_Array.cpp b/src/CLR/Core/CLR_RT_HeapBlock_Array.cpp
index 7939644212..a5293a8987 100644
--- a/src/CLR/Core/CLR_RT_HeapBlock_Array.cpp
+++ b/src/CLR/Core/CLR_RT_HeapBlock_Array.cpp
@@ -18,6 +18,8 @@ HRESULT CLR_RT_HeapBlock_Array::CreateInstance(
CLR_RT_HeapBlock_Array *pArray;
CLR_RT_TypeDef_Index cls;
CLR_RT_TypeDef_Instance inst{};
+ CLR_RT_TypeDescriptor desc{};
+ CLR_RT_ReflectionDef_Index workingReflex = reflex;
reference.SetObjectReference(nullptr);
@@ -26,12 +28,31 @@ HRESULT CLR_RT_HeapBlock_Array::CreateInstance(
if (reflex.kind != REFLECTION_TYPE)
{
- NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
+ // check for typespec
+ if (reflex.kind == REFLECTION_TYPESPEC)
+ {
+ // get the type descriptor for the typespec
+ (desc.InitializeFromTypeSpec(reflex.data.typeSpec));
+
+ // check that this ends up being a reflecion type
+ if (desc.m_reflex.kind != REFLECTION_TYPE)
+ {
+ NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
+ }
+
+ // copy over to working reflex
+ workingReflex = desc.m_reflex;
+ workingReflex.levels++;
+ }
+ else
+ {
+ NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
+ }
}
- if (reflex.levels == 1)
+ if (workingReflex.levels == 1)
{
- cls = reflex.data.type;
+ cls = workingReflex.data.type;
}
else
{
@@ -104,7 +125,7 @@ HRESULT CLR_RT_HeapBlock_Array::CreateInstance(
}
else if (def.ResolveToken(tk, assm))
{
- NANOCLR_CHECK_HRESULT(ref.SetReflection(def, caller->genericType));
+ NANOCLR_CHECK_HRESULT(ref.SetReflection((CLR_RT_TypeSpec_Index)def));
}
else
{
diff --git a/src/CLR/Core/Execution.cpp b/src/CLR/Core/Execution.cpp
index f1629f98e5..e31e66e3be 100644
--- a/src/CLR/Core/Execution.cpp
+++ b/src/CLR/Core/Execution.cpp
@@ -1559,6 +1559,8 @@ CLR_RT_HeapBlock *CLR_RT_ExecutionEngine::ExtractHeapBlocksForGenericInstance(
{
NATIVE_PROFILE_CLR_CORE();
+ (void)genericType;
+
if (length > CLR_RT_HeapBlock::HB_MaxSize)
{
return nullptr;
@@ -1567,9 +1569,11 @@ CLR_RT_HeapBlock *CLR_RT_ExecutionEngine::ExtractHeapBlocksForGenericInstance(
flags = flags | CLR_RT_HeapBlock::HB_InitializeToZero;
CLR_RT_HeapBlock *hb = ExtractHeapBlocks(m_heap, DATATYPE_GENERICINST, flags, length);
+ _ASSERTE(true);
+
if (hb)
{
- hb->SetGenericInstanceObject(genericType);
+ // hb->SetGenericInstanceObject(genericType);
#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS)
g_CLR_PRF_Profiler.TrackObjectCreation(hb);
@@ -1821,7 +1825,10 @@ CLR_RT_HeapBlock *CLR_RT_ExecutionEngine::AccessStaticField(const CLR_RT_FieldDe
return nullptr;
}
-HRESULT CLR_RT_ExecutionEngine::InitializeReference(CLR_RT_HeapBlock &ref, CLR_RT_SignatureParser &parser)
+HRESULT CLR_RT_ExecutionEngine::InitializeReference(
+ CLR_RT_HeapBlock &ref,
+ CLR_RT_SignatureParser &parser,
+ const CLR_RT_TypeSpec_Instance *genericInstance)
{
NATIVE_PROFILE_CLR_CORE();
//
@@ -1832,12 +1839,16 @@ HRESULT CLR_RT_ExecutionEngine::InitializeReference(CLR_RT_HeapBlock &ref, CLR_R
NANOCLR_HEADER();
+ CLR_RT_SignatureParser internalParser{};
CLR_RT_SignatureParser::Element res;
NanoCLRDataType dt;
+ CLR_RT_TypeDef_Index realTypeDef{};
+ CLR_RT_TypeSpec_Instance internalGenericInstance{};
NANOCLR_CHECK_HRESULT(parser.Advance(res));
dt = res.DataType;
+ realTypeDef.data = res.Class.data;
if (res.Levels > 0) // Array
{
@@ -1845,10 +1856,58 @@ HRESULT CLR_RT_ExecutionEngine::InitializeReference(CLR_RT_HeapBlock &ref, CLR_R
}
else
{
- if (dt == DATATYPE_VALUETYPE)
+ process_datatype:
+
+ if (dt == DATATYPE_VAR)
+ {
+ genericInstance->assembly
+ ->FindGenericParamAtTypeSpec(genericInstance->data, res.GenericParamPosition, realTypeDef, dt);
+
+ goto process_datatype;
+ }
+ else if (dt == DATATYPE_MVAR)
+ {
+ _ASSERTE(true);
+
+ goto process_datatype;
+ }
+ else if (dt == DATATYPE_GENERICINST)
+ {
+ // need to unwind one position in the signature to have the complete one to seach TypeSpecs
+ CLR_PMETADATA typeSpecSignature = parser.Signature;
+ typeSpecSignature--;
+
+ CLR_RT_TypeSpec_Index genericTSIndex = {};
+ if (!parser.Assembly->FindTypeSpec(typeSpecSignature, genericTSIndex))
+ {
+ NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
+ }
+
+ // copy over to parameter
+ internalGenericInstance.InitializeFromIndex(genericTSIndex);
+
+ internalParser.Initialize_TypeSpec(
+ parser.Assembly,
+ parser.Assembly->GetTypeSpec(internalGenericInstance.TypeSpec()));
+
+ CLR_RT_SignatureParser::Element element;
+ NANOCLR_CHECK_HRESULT(internalParser.Advance(element));
+
+ // if this is another generic instance, need to advance to get the type
+ if (dt == DATATYPE_GENERICINST)
+ {
+ NANOCLR_CHECK_HRESULT(internalParser.Advance(element));
+ }
+
+ dt = element.DataType;
+ realTypeDef.data = element.Class.data;
+
+ goto process_datatype;
+ }
+ else if (dt == DATATYPE_VALUETYPE)
{
CLR_RT_TypeDef_Instance inst{};
- inst.InitializeFromIndex(res.Class);
+ inst.InitializeFromIndex(realTypeDef);
if ((inst.target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) == CLR_RECORD_TYPEDEF::TD_Semantics_Enum)
{
@@ -1856,7 +1915,11 @@ HRESULT CLR_RT_ExecutionEngine::InitializeReference(CLR_RT_HeapBlock &ref, CLR_R
}
else
{
- NANOCLR_SET_AND_LEAVE(NewObject(ref, inst));
+ // prefer the generic instance contained in the signature
+ NANOCLR_SET_AND_LEAVE(NewObject(
+ ref,
+ inst,
+ NANOCLR_INDEX_IS_VALID(internalGenericInstance) ? &internalGenericInstance : genericInstance));
}
}
else
@@ -1877,7 +1940,8 @@ HRESULT CLR_RT_ExecutionEngine::InitializeReference(CLR_RT_HeapBlock &ref, CLR_R
HRESULT CLR_RT_ExecutionEngine::InitializeReference(
CLR_RT_HeapBlock &ref,
const CLR_RECORD_FIELDDEF *target,
- CLR_RT_Assembly *assm)
+ CLR_RT_Assembly *assm,
+ const CLR_RT_TypeSpec_Instance *genericInstance)
{
NATIVE_PROFILE_CLR_CORE();
NANOCLR_HEADER();
@@ -1885,7 +1949,7 @@ HRESULT CLR_RT_ExecutionEngine::InitializeReference(
CLR_RT_SignatureParser parser{};
parser.Initialize_FieldDef(assm, target);
- NANOCLR_SET_AND_LEAVE(InitializeReference(ref, parser));
+ NANOCLR_SET_AND_LEAVE(InitializeReference(ref, parser, genericInstance));
NANOCLR_NOCLEANUP();
}
@@ -1897,11 +1961,13 @@ HRESULT CLR_RT_ExecutionEngine::InitializeLocals(
const CLR_RT_MethodDef_Instance &methodDefInstance)
{
NATIVE_PROFILE_CLR_CORE();
- //
- // WARNING!!!
- //
- // This method is a shortcut for the following code:
- //
+
+ //////////////////////////////////////////////////////////////////////
+ // //
+ // ***** WARNING ***** //
+ // //
+ // Changes here must be ported to "CLR_RT_SignatureParser::Advance" //
+ //////////////////////////////////////////////////////////////////////
NANOCLR_HEADER();
@@ -1910,6 +1976,7 @@ HRESULT CLR_RT_ExecutionEngine::InitializeLocals(
CLR_PMETADATA sig = assembly->GetSignature(methodDef->locals);
CLR_UINT32 count = methodDef->localsCount;
bool fZeroed = false;
+ CLR_RT_TypeSpec_Instance genericInstance = {};
while (count)
{
@@ -1958,53 +2025,95 @@ HRESULT CLR_RT_ExecutionEngine::InitializeLocals(
}
case DATATYPE_GENERICINST:
- // need to rewind the signature so that the ELEMENT_TYPE is present
- // otherwise the comparison won't be possible
- sig--;
+ {
+ // need to unwind one position in the signature to have the complete one to seach TypeSpecs
+ CLR_PMETADATA typeSpecSignature = sig;
+ typeSpecSignature--;
+
+ CLR_RT_TypeSpec_Index genericTSIndex = {};
+
+ if (methodDefInstance.genericType && methodDefInstance.genericType->data != 0)
+ {
+ // method is generic, it can only use class from method's class generic parameters
+ genericInstance.InitializeFromIndex(*methodDefInstance.genericType);
+ }
+ else
+ {
+ if (!assembly->FindTypeSpec(typeSpecSignature, genericTSIndex))
+ {
+ NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
+ }
- // Parse the TypeSpec signature to get the instantiated element
- CLR_RT_SignatureParser sp;
- sp.Initialize_TypeSpec(assembly, sig);
+ // copy over to parameter
+ genericInstance.InitializeFromIndex(genericTSIndex);
+ }
+
+ CLR_RT_SignatureParser parser;
+ parser.Initialize_TypeSpec(genericInstance);
CLR_RT_SignatureParser::Element element;
- NANOCLR_CHECK_HRESULT(sp.Advance(element));
+ NANOCLR_CHECK_HRESULT(parser.Advance(element));
+
+ // if this is another generic instance, need to advance to get the type
+ if (dt == DATATYPE_GENERICINST)
+ {
+ NANOCLR_CHECK_HRESULT(parser.Advance(element));
+ }
- // element.Class and element.DataType represent the T
cls = element.Class;
dt = element.DataType;
+ // done, now consume the remaining of the local var signature
+ CLR_RT_SignatureParser varParser;
+ varParser.Initialize_LocalVar(assembly, typeSpecSignature);
+
+ CLR_RT_SignatureParser::Element varElement;
+ // consume GENERICINST
+ varParser.Advance(varElement);
+ // consume class|valuetype
+ varParser.Advance(varElement);
+
+ // consume parameters
+ for (int paramIndex = 0; paramIndex < varParser.GenParamCount; paramIndex++)
+ {
+ NANOCLR_CHECK_HRESULT(varParser.Advance(varElement));
+ }
+
+ // advance locals signature
+ while (sig < varParser.Signature)
+ {
+ sig++;
+ }
+
goto done;
+ }
case DATATYPE_VAR:
{
// type-level generic parameter in a locals signature (e.g. 'T' inside a generic type)
CLR_INT8 genericParamPosition = *sig++;
- // parse the locals-signature to extract that T
- CLR_RT_SignatureParser parser;
- parser.Initialize_MethodLocals(assembly, methodDef);
- CLR_RT_SignatureParser::Element sigElement;
-
- // ensure we don’t walk past the available generic parameters
- const int maxParams = methodDefInstance.target->genericParamCount;
- if (genericParamPosition < 0 || genericParamPosition > maxParams)
+ if (methodDefInstance.genericType && methodDefInstance.genericType->data != 0)
{
- NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
+ CLR_RT_TypeSpec_Instance typeSpec{};
+ typeSpec.InitializeFromIndex(
+ (const CLR_RT_TypeSpec_Index &)methodDefInstance.genericType->data);
+
+ typeSpec.assembly->FindGenericParamAtTypeSpec(
+ methodDefInstance.genericType->TypeSpec(),
+ genericParamPosition,
+ cls,
+ dt);
}
-
- // advance into the VAR entry
- parser.Advance(sigElement);
-
- // walk forward to the Nth generic-parameter
- for (int i = 0; i < genericParamPosition; i++)
+ else
{
- parser.Advance(sigElement);
+ assembly->FindGenericParamAtTypeSpec(
+ methodDefInstance.genericType->TypeSpec(),
+ genericParamPosition,
+ cls,
+ dt);
}
- // element.Class and element.DataType represent the T
- cls = sigElement.Class;
- dt = sigElement.DataType;
-
goto done;
}
@@ -2084,7 +2193,14 @@ HRESULT CLR_RT_ExecutionEngine::InitializeLocals(
} while (++ptr < ptrEnd);
}
- NANOCLR_CHECK_HRESULT(NewObject(*locals, inst));
+ // if (isGenericInstance)
+ //{
+ // NANOCLR_CHECK_HRESULT(NewGenericInstanceObject(*locals, inst, &genericInstance));
+ // }
+ // else
+ {
+ NANOCLR_CHECK_HRESULT(NewObject(*locals, inst, &genericInstance));
+ }
}
}
else
@@ -2108,7 +2224,10 @@ HRESULT CLR_RT_ExecutionEngine::InitializeLocals(
//--//
-HRESULT CLR_RT_ExecutionEngine::NewObjectFromIndex(CLR_RT_HeapBlock &reference, const CLR_RT_TypeDef_Index &cls)
+HRESULT CLR_RT_ExecutionEngine::NewObjectFromIndex(
+ CLR_RT_HeapBlock &reference,
+ const CLR_RT_TypeDef_Index &cls,
+ const CLR_RT_TypeSpec_Instance *genericInstance)
{
NATIVE_PROFILE_CLR_CORE();
NANOCLR_HEADER();
@@ -2118,12 +2237,15 @@ HRESULT CLR_RT_ExecutionEngine::NewObjectFromIndex(CLR_RT_HeapBlock &reference,
if (inst.InitializeFromIndex(cls) == false)
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
- NANOCLR_SET_AND_LEAVE(NewObject(reference, inst));
+ NANOCLR_SET_AND_LEAVE(NewObject(reference, inst, genericInstance));
NANOCLR_NOCLEANUP();
}
-HRESULT CLR_RT_ExecutionEngine::NewObject(CLR_RT_HeapBlock &reference, const CLR_RT_TypeDef_Instance &inst)
+HRESULT CLR_RT_ExecutionEngine::NewObject(
+ CLR_RT_HeapBlock &reference,
+ const CLR_RT_TypeDef_Instance &inst,
+ const CLR_RT_TypeSpec_Instance *genericInstance)
{
NATIVE_PROFILE_CLR_CORE();
NANOCLR_HEADER();
@@ -2174,7 +2296,15 @@ HRESULT CLR_RT_ExecutionEngine::NewObject(CLR_RT_HeapBlock &reference, const CLR
{
int clsFields = inst.target->instanceFieldsCount;
int totFields = inst.CrossReference().totalFields + CLR_RT_HeapBlock::HB_Object_Fields_Offset;
- CLR_RT_HeapBlock *obj = ExtractHeapBlocksForClassOrValueTypes(dt, 0, inst, totFields);
+
+ CLR_UINT32 flags = 0;
+
+ if (genericInstance != nullptr && NANOCLR_INDEX_IS_VALID(*genericInstance))
+ {
+ flags |= CLR_RT_HeapBlock::HB_GenericInstance;
+ }
+
+ CLR_RT_HeapBlock *obj = ExtractHeapBlocksForClassOrValueTypes(dt, flags, inst, totFields);
CHECK_ALLOCATION(obj);
reference.SetObjectReference(obj);
@@ -2186,11 +2316,17 @@ HRESULT CLR_RT_ExecutionEngine::NewObject(CLR_RT_HeapBlock &reference, const CLR
NANOCLR_CHECK_HRESULT(obj->SetObjectCls(inst));
+ if (genericInstance != nullptr && NANOCLR_INDEX_IS_VALID(*genericInstance))
+ {
+ // If we have a generic instance, we need to set the corresponding TypeSpec
+ obj->SetGenericInstanceType(*genericInstance);
+ }
+
//
// Initialize field types, from last to first.
//
- // We do the decrement BEFORE the comparison because we want to stop short of the first field, the
- // object descriptor (already initialized).
+ // We do the decrement BEFORE the comparison because we want to stop short of the first field,
+ // the object descriptor (already initialized).
//
obj += totFields;
while (--totFields > 0)
@@ -2214,7 +2350,12 @@ HRESULT CLR_RT_ExecutionEngine::NewObject(CLR_RT_HeapBlock &reference, const CLR
target--;
clsFields--;
- NANOCLR_CHECK_HRESULT(InitializeReference(*obj, target, assm));
+#if defined(NANOCLR_INSTANCE_NAMES)
+ const char *typeName = assm->GetString(target->type);
+ const char *fieldName = assm->GetString(target->name);
+#endif
+
+ NANOCLR_CHECK_HRESULT(InitializeReference(*obj, target, assm, genericInstance));
}
}
@@ -2225,9 +2366,6 @@ HRESULT CLR_RT_ExecutionEngine::NewObject(CLR_RT_HeapBlock &reference, const CLR
}
break;
- case DATATYPE_GENERICINST:
- break;
-
default:
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
@@ -2256,19 +2394,19 @@ HRESULT CLR_RT_ExecutionEngine::NewObject(CLR_RT_HeapBlock &reference, CLR_UINT3
HRESULT CLR_RT_ExecutionEngine::NewGenericInstanceObject(
CLR_RT_HeapBlock &reference,
const CLR_RT_TypeDef_Instance &typeDef,
- const CLR_RT_TypeSpec_Index &genericType)
+ const CLR_RT_TypeSpec_Index *genericType)
{
NATIVE_PROFILE_CLR_CORE();
NANOCLR_HEADER();
CLR_RT_TypeSpec_Instance inst;
- if (inst.InitializeFromIndex(genericType) == false)
+ if (inst.InitializeFromIndex(*genericType) == false)
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
- NANOCLR_SET_AND_LEAVE(NewGenericInstanceObject(reference, typeDef, inst));
+ NANOCLR_SET_AND_LEAVE(NewGenericInstanceObject(reference, typeDef, &inst));
NANOCLR_NOCLEANUP();
}
@@ -2276,7 +2414,7 @@ HRESULT CLR_RT_ExecutionEngine::NewGenericInstanceObject(
HRESULT CLR_RT_ExecutionEngine::NewGenericInstanceObject(
CLR_RT_HeapBlock &reference,
const CLR_RT_TypeDef_Instance &instance,
- CLR_RT_TypeSpec_Instance &genericInstance)
+ const CLR_RT_TypeSpec_Instance *genericInstance)
{
NATIVE_PROFILE_CLR_CORE();
NANOCLR_HEADER();
@@ -2292,7 +2430,7 @@ HRESULT CLR_RT_ExecutionEngine::NewGenericInstanceObject(
int clsFields = instance.target->instanceFieldsCount;
int totFields = instance.CrossReference().totalFields + CLR_RT_HeapBlock::HB_Object_Fields_Offset;
- giHeader = (CLR_RT_HeapBlock_GenericInstance *)ExtractHeapBlocksForGenericInstance(0, genericInstance, totFields);
+ giHeader = (CLR_RT_HeapBlock_GenericInstance *)ExtractHeapBlocksForGenericInstance(0, *genericInstance, totFields);
CHECK_ALLOCATION(giHeader);
reference.SetObjectReference(giHeader);
@@ -2332,7 +2470,7 @@ HRESULT CLR_RT_ExecutionEngine::NewGenericInstanceObject(
target--;
clsFields--;
- NANOCLR_CHECK_HRESULT(InitializeReference(*fieldCursor, target, assm));
+ NANOCLR_CHECK_HRESULT(InitializeReference(*fieldCursor, target, assm, genericInstance));
}
if (instance.HasFinalizer())
@@ -2378,11 +2516,18 @@ HRESULT CLR_RT_ExecutionEngine::CloneObject(CLR_RT_HeapBlock &reference, const C
// Save the pointer to the object to clone, in case 'reference' and 'source' point to the same block.
//
CLR_RT_HeapBlock safeSource;
+ CLR_RT_TypeSpec_Instance genericInstance = {};
safeSource.SetObjectReference(obj);
CLR_RT_ProtectFromGC gc(safeSource);
- NANOCLR_CHECK_HRESULT(NewObjectFromIndex(reference, obj->ObjectCls()));
+ if (obj->IsAGenericInstance())
+ {
+ // instanciate the generic type
+ genericInstance.InitializeFromIndex(obj->ObjectGenericType());
+ }
+
+ NANOCLR_CHECK_HRESULT(NewObjectFromIndex(reference, obj->ObjectCls(), &genericInstance));
NANOCLR_CHECK_HRESULT(CopyValueType(reference.Dereference(), obj));
}
break;
diff --git a/src/CLR/Core/Interpreter.cpp b/src/CLR/Core/Interpreter.cpp
index ba41d2ff27..1916bd7af6 100644
--- a/src/CLR/Core/Interpreter.cpp
+++ b/src/CLR/Core/Interpreter.cpp
@@ -5,6 +5,8 @@
//
#include "Core.h"
+typedef Library_corlib_native_System_Nullable_1 Sys_Nullable;
+
////////////////////////////////////////////////////////////////////////////////////////////////////
#if defined(NANOCLR_TRACE_EXCEPTIONS) && defined(VIRTUAL_DEVICE)
@@ -2394,10 +2396,11 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
// check that...
//
changes = -calleeInst.target->argumentsCount;
- NANOCLR_CHECK_HRESULT(CLR_Checks::VerifyStackOK(
- *stack,
- stack->m_evalStackPos,
- changes)); // Check to see if we have enough parameters.
+ NANOCLR_CHECK_HRESULT(
+ CLR_Checks::VerifyStackOK(
+ *stack,
+ stack->m_evalStackPos,
+ changes)); // Check to see if we have enough parameters.
stack->m_evalStackPos += changes;
top = stack->m_evalStackPos++; // Push back the result.
@@ -2433,10 +2436,11 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
else
{
changes = calleeInst.target->argumentsCount;
- NANOCLR_CHECK_HRESULT(CLR_Checks::VerifyStackOK(
- *stack,
- stack->m_evalStackPos,
- -changes)); // Check to see if we have enough parameters.
+ NANOCLR_CHECK_HRESULT(
+ CLR_Checks::VerifyStackOK(
+ *stack,
+ stack->m_evalStackPos,
+ -changes)); // Check to see if we have enough parameters.
top = stack->m_evalStackPos;
//
@@ -2461,8 +2465,11 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
}
else
{
- NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine
- .NewGenericInstanceObject(top[0], cls, *calleeInst.genericType));
+ CLR_RT_TypeSpec_Instance calleeInstGenericType;
+ calleeInstGenericType.InitializeFromIndex(*calleeInst.genericType);
+
+ NANOCLR_CHECK_HRESULT(
+ g_CLR_RT_ExecutionEngine.NewObject(top[0], cls, &calleeInstGenericType));
}
//
@@ -2561,7 +2568,7 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
FETCH_ARG_COMPRESSED_FIELDTOKEN(arg, ip);
CLR_RT_FieldDef_Instance fieldInst;
- if (fieldInst.ResolveToken(arg, assm) == false)
+ if (fieldInst.ResolveToken(arg, assm, &stack->m_call) == false)
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
@@ -2615,7 +2622,7 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
FETCH_ARG_COMPRESSED_FIELDTOKEN(arg, ip);
CLR_RT_FieldDef_Instance fieldInst;
- if (fieldInst.ResolveToken(arg, assm) == false)
+ if (fieldInst.ResolveToken(arg, assm, &stack->m_call) == false)
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
@@ -2659,7 +2666,7 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
CHECKSTACK(stack, evalPos);
CLR_RT_FieldDef_Instance fieldInst;
- if (fieldInst.ResolveToken(arg, assm) == false)
+ if (fieldInst.ResolveToken(arg, assm, &stack->m_call) == false)
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
@@ -2713,7 +2720,7 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
FETCH_ARG_COMPRESSED_FIELDTOKEN(arg, ip);
CLR_RT_FieldDef_Instance field;
- if (field.ResolveToken(arg, assm) == false)
+ if (field.ResolveToken(arg, assm, &stack->m_call) == false)
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
@@ -2741,7 +2748,7 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
FETCH_ARG_COMPRESSED_FIELDTOKEN(arg, ip);
CLR_RT_FieldDef_Instance field;
- if (field.ResolveToken(arg, assm) == false)
+ if (field.ResolveToken(arg, assm, &stack->m_call) == false)
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
@@ -2768,7 +2775,7 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
FETCH_ARG_COMPRESSED_FIELDTOKEN(arg, ip);
CLR_RT_FieldDef_Instance field;
- if (field.ResolveToken(arg, assm) == false)
+ if (field.ResolveToken(arg, assm, &stack->m_call) == false)
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
@@ -2802,13 +2809,101 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
UPDATESTACK(stack, evalPos);
+ // check if value is a nullable type
+ bool hasValue = false;
+ CLR_RT_HeapBlock *nullableValue = nullptr;
+ bool valueIsNullableType = false;
+ bool tokenIsNullableType = false;
+ CLR_RT_TypeDef_Instance destinationType;
+
+ valueIsNullableType =
+ CLR_RT_ExecutionEngine::IsInstanceOf(evalPos[0], g_CLR_RT_WellKnownTypes.Nullable);
+ tokenIsNullableType =
+ CLR_RT_ExecutionEngine::IsInstanceOf(typeInst, g_CLR_RT_WellKnownTypes.Nullable);
+
+ // resolve the T to box to / unbox from
+ if (tokenIsNullableType && destinationType.ResolveNullableType(arg, assm, &stack->m_call) == false)
+ {
+ NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
+ }
+
+ if (valueIsNullableType)
+ {
+ // check HasValue property
+ nullableValue = evalPos[0].Dereference();
+ hasValue = nullableValue[Library_corlib_native_System_Nullable_1::FIELD__hasValue]
+ .NumericByRefConst()
+ .u1;
+ }
+
if (op == CEE_BOX)
{
- NANOCLR_CHECK_HRESULT(evalPos[0].PerformBoxing(typeInst));
+ if (tokenIsNullableType)
+ {
+ if (!hasValue)
+ {
+ // box a null reference
+ evalPos[0].SetObjectReference(nullptr);
+ }
+ else
+ {
+ // reach the value to box
+ CLR_RT_HeapBlock &value =
+ nullableValue[Library_corlib_native_System_Nullable_1::FIELD__value];
+
+ // box the value
+ NANOCLR_CHECK_HRESULT(value.PerformBoxing(destinationType));
+
+ // assign the boxed result back to the evaluation stack
+ evalPos[0].Assign(value);
+ }
+ }
+ else
+ {
+ NANOCLR_CHECK_HRESULT(evalPos[0].PerformBoxing(typeInst));
+ }
}
else
{
- NANOCLR_CHECK_HRESULT(evalPos[0].PerformUnboxing(typeInst));
+ if (tokenIsNullableType)
+ {
+ // create a Nullable...
+ CLR_RT_HeapBlock nullableObject;
+ CLR_RT_TypeSpec_Index destinationTypeSpec;
+ destinationTypeSpec.data = arg;
+
+ NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewGenericInstanceObject(
+ nullableObject,
+ typeInst,
+ &destinationTypeSpec));
+
+ CLR_RT_ProtectFromGC gc(nullableObject);
+
+ if (evalPos[0].Dereference() == nullptr)
+ {
+ // assign a null reference (already carried out by NewObjectFromIndex)
+ // set HasValue to false
+ nullableObject.Dereference()[Sys_Nullable::FIELD__hasValue].SetBoolean(false);
+ }
+ else
+ {
+ // unbox the T value...
+ NANOCLR_CHECK_HRESULT(evalPos[0].PerformUnboxing(destinationType));
+
+ // assign the copied unboxed value
+ nullableObject.Dereference()[Sys_Nullable::FIELD__value].Assign(evalPos[0]);
+
+ // set HasValue to true
+ nullableObject.Dereference()[Sys_Nullable::FIELD__hasValue].SetBoolean(true);
+ }
+
+ // assign the Nullable object to the evaluation stack
+ evalPos[0].SetObjectReference(nullableObject.Dereference());
+ }
+ else
+ {
+ NANOCLR_CHECK_HRESULT(evalPos[0].PerformUnboxing(typeInst));
+ }
}
break;
}
@@ -2825,6 +2920,8 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
// ldobj.) When applied to a reference type, the unbox.any instruction has the same effect as
// castclass typeTok.
+ // TODO: still not handling Nullable types here
+
CLR_RT_TypeDef_Instance typeInst{};
if (typeInst.ResolveToken(arg, assm, &stack->m_call) == false)
{
@@ -3216,7 +3313,7 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
- evalPos[0].SetReflection(tsInst, stack->m_call.genericType);
+ evalPos[0].SetReflection((const CLR_RT_TypeSpec_Index &)tsInst.data);
}
break;
@@ -3237,7 +3334,7 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
case TBL_FieldDef:
{
CLR_RT_FieldDef_Instance field;
- if (field.ResolveToken(arg, assm) == false)
+ if (field.ResolveToken(arg, assm, &stack->m_call) == false)
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
@@ -3261,8 +3358,8 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
case TBL_GenericParam:
{
- CLR_RT_GenericParam_Instance param;
- if (param.ResolveToken(arg, assm) == false)
+ CLR_RT_GenericParam_Instance genericParam;
+ if (genericParam.ResolveToken(arg, assm) == false)
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
@@ -3286,37 +3383,12 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
if (gpCR.typeOrMethodDef == TBL_MethodDef)
{
// Method generic parameter (!!T)
-
- CLR_RT_MethodSpec_Index msIndex;
- if (!resolveAsm->FindMethodSpecFromTypeSpec(
- stack->m_call.genericType->TypeSpec(),
- msIndex))
- {
- NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
- }
-
- CLR_RT_MethodSpec_Instance ms;
- if (ms.InitializeFromIndex(msIndex) == false)
- {
- NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
- }
-
- int genericParamPos = param.GenericParam();
-
- CLR_RT_SignatureParser parser;
- CLR_RT_SignatureParser::Element element;
- parser.Initialize_MethodSignature(&ms);
-
- for (int i = 0; i <= genericParamPos; i++)
- {
- NANOCLR_CHECK_HRESULT(parser.Advance(element));
- }
-
- evalPos[0].SetReflection(element.Class);
+ // already resolved
+ evalPos[0].SetReflection(gpCR.classTypeDef);
}
else
{
- // type generic parameter (!T)
+ // Type generic parameter (!T)
if (stack->m_call.genericType == nullptr)
{
// No closed‐generic context available: fall back to returning the
@@ -3334,7 +3406,7 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
if (!resolveAsm->FindGenericParamAtTypeSpec(
callerTypeSpec->TypeSpec(),
- param.target->number,
+ genericParam.target->number,
resolvedTypeDef,
dummyDataType))
{
diff --git a/src/CLR/Core/TypeSystem.cpp b/src/CLR/Core/TypeSystem.cpp
index 4c8fc7669c..57bee990d8 100644
--- a/src/CLR/Core/TypeSystem.cpp
+++ b/src/CLR/Core/TypeSystem.cpp
@@ -216,6 +216,19 @@ void CLR_RT_SignatureParser::Initialize_TypeSpec(CLR_RT_Assembly *assm, CLR_PMET
IsGenericInst = false;
}
+void CLR_RT_SignatureParser::Initialize_TypeSpec(CLR_RT_TypeSpec_Instance tsInstance)
+{
+ NATIVE_PROFILE_CLR_CORE();
+
+ Assembly = tsInstance.assembly;
+ Signature = Assembly->GetSignature(tsInstance.target->signature);
+
+ Type = CLR_RT_SignatureParser::c_TypeSpec;
+ Flags = 0;
+ ParamCount = 1;
+ GenParamCount = 0;
+ IsGenericInst = false;
+}
//--//
void CLR_RT_SignatureParser::Initialize_Interfaces(CLR_RT_Assembly *assm, const CLR_RECORD_TYPEDEF *td)
@@ -412,6 +425,21 @@ void CLR_RT_SignatureParser::Initialize_MethodLocals(CLR_RT_Assembly *assm, cons
IsGenericInst = false;
}
+void CLR_RT_SignatureParser::Initialize_LocalVar(CLR_RT_Assembly *assm, const CLR_PMETADATA sig)
+{
+ NATIVE_PROFILE_CLR_CORE();
+
+ Assembly = assm;
+ Signature = sig;
+
+ Type = CLR_RT_SignatureParser::c_Locals;
+ Flags = 0;
+ ParamCount = 1;
+
+ GenParamCount = 0;
+ IsGenericInst = false;
+}
+
//--//
void CLR_RT_SignatureParser::Initialize_Objects(CLR_RT_HeapBlock *lst, int count, bool fTypes)
@@ -432,11 +460,13 @@ void CLR_RT_SignatureParser::Initialize_Objects(CLR_RT_HeapBlock *lst, int count
HRESULT CLR_RT_SignatureParser::Advance(Element &res)
{
NATIVE_PROFILE_CLR_CORE();
- //
- // WARNING!!!
- //
- // If you change this method, change "CLR_RT_ExecutionEngine::InitializeLocals" too.
- //
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // //
+ // ***** WARNING ***** //
+ // //
+ // Changes here must be ported to "CLR_RT_ExecutionEngine::InitializeLocals" //
+ ///////////////////////////////////////////////////////////////////////////////
NANOCLR_HEADER();
@@ -539,7 +569,6 @@ HRESULT CLR_RT_SignatureParser::Advance(Element &res)
case DATATYPE_CLASS:
case DATATYPE_VALUETYPE:
{
- parse_type:
CLR_UINT32 tk = CLR_TkFromStream(Signature);
CLR_UINT32 index = CLR_DataFromTk(tk);
@@ -603,24 +632,7 @@ HRESULT CLR_RT_SignatureParser::Advance(Element &res)
{
// set flag for GENERICINST
IsGenericInst = true;
-
- // get data type
- auto dt = (NanoCLRDataType)*Signature++;
-
- // sanity check
- if (dt == DATATYPE_CLASS || dt == DATATYPE_VALUETYPE)
- {
- res.DataType = dt;
-
- // parse type
- goto parse_type;
- }
- else
- {
- NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
- }
-
- break;
+ NANOCLR_SET_AND_LEAVE(S_OK);
}
case DATATYPE_VAR:
@@ -696,10 +708,16 @@ bool CLR_RT_TypeSpec_Instance::InitializeFromIndex(const CLR_RT_TypeSpec_Index &
CLR_RT_SignatureParser::Element element;
- // get type
+ // if this is a generic, advance another one
parser.Advance(element);
- typeDefIndex = element.Class.Type();
+ if (element.DataType == DATATYPE_GENERICINST)
+ {
+ // this is a generic instance, so we need to advance one more time
+ parser.Advance(element);
+
+ genericTypeDef = element.Class;
+ }
return true;
}
@@ -732,6 +750,21 @@ bool CLR_RT_TypeSpec_Instance::ResolveToken(CLR_UINT32 token, CLR_RT_Assembly *a
assembly = assm;
target = assm->GetTypeSpec(index);
+ CLR_RT_SignatureParser parser;
+ parser.Initialize_TypeSpec(assembly, assembly->GetTypeSpec(index));
+
+ CLR_RT_SignatureParser::Element element;
+
+ // if this is a generic, advance another one
+ parser.Advance(element);
+
+ if (element.DataType == DATATYPE_GENERICINST)
+ {
+ // this is a generic instance, so we need to advance one more time
+ parser.Advance(element);
+
+ genericTypeDef = element.Class;
+ }
return true;
}
@@ -770,6 +803,31 @@ bool CLR_RT_TypeDef_Instance::InitializeFromReflection(const CLR_RT_ReflectionDe
ptr = &cls;
}
break;
+
+ case REFLECTION_TYPESPEC:
+ assembly = g_CLR_RT_TypeSystem.m_assemblies[reflex.data.typeSpec.Assembly() - 1];
+
+ const CLR_RECORD_TYPESPEC *ts = assembly->GetTypeSpec(reflex.data.typeSpec.TypeSpec());
+
+ CLR_RT_SignatureParser parser;
+ parser.Initialize_TypeSpec(assembly, ts);
+
+ CLR_RT_SignatureParser::Element element;
+ if (FAILED(parser.Advance(element)))
+ {
+ return false;
+ }
+
+ *levels = element.Levels;
+
+ // if this is a generic type, need to advance to get type
+ if (element.DataType == DATATYPE_GENERICINST)
+ {
+ parser.Advance(element);
+ }
+
+ ptr = &element.Class;
+ break;
}
return ptr ? InitializeFromIndex(*ptr) : false;
@@ -970,98 +1028,126 @@ bool CLR_RT_TypeDef_Instance::ResolveToken(
case TBL_TypeSpec:
{
- // Grab the raw signature for the IL token (e.g. !T[], List`1, etc.)
- const CLR_RECORD_TYPESPEC *ts = assm->GetTypeSpec(index);
- CLR_RT_SignatureParser parser;
- parser.Initialize_TypeSpec(assm, ts);
-
- CLR_RT_SignatureParser::Element elem;
+ const CLR_RT_TypeSpec_Index typeSpecIdx = assm->crossReferenceTypeSpec[index].genericType;
+ CLR_RT_TypeSpec_Instance typeSpecInstance{};
+ typeSpecInstance.InitializeFromIndex(typeSpecIdx);
- // Skip any leading SZARRAY or BYREF
- do
+ if (NANOCLR_INDEX_IS_VALID(typeSpecInstance.genericTypeDef))
{
- if (FAILED(parser.Advance(elem)))
- {
- return false;
- }
- } while (elem.DataType == DATATYPE_SZARRAY || elem.DataType == DATATYPE_BYREF);
-
- // If this is a closed‐generic instantiation header, peel off the wrapper
- if (elem.DataType == DATATYPE_GENERICINST)
+ // this is a generic type definition
+ data = typeSpecInstance.genericTypeDef.data;
+ assembly = g_CLR_RT_TypeSystem.m_assemblies[typeSpecInstance.genericTypeDef.Assembly() - 1];
+ target = assembly->GetTypeDef(typeSpecInstance.genericTypeDef.Type());
+ }
+ else
{
- // consume the CLASS/VALUETYPE marker
+ // this a generic parameter
+ const CLR_RECORD_TYPESPEC *ts = assm->GetTypeSpec(index);
+ CLR_RT_SignatureParser parser;
+ parser.Initialize_TypeSpec(assm, ts);
+
+ CLR_RT_SignatureParser::Element elem;
if (FAILED(parser.Advance(elem)))
{
return false;
}
- // consume the generic‐definition token itself
- if (FAILED(parser.Advance(elem)))
+
+ if (elem.Levels > 0)
{
+ // this is an array, can't init like this
return false;
}
- // consume the count of generic arguments
- if (FAILED(parser.Advance(elem)))
+ else
{
- return false;
- }
- }
+ if (elem.DataType == DATATYPE_GENERICINST)
+ {
+ if (FAILED(parser.Advance(elem)))
+ {
+ return false;
+ }
- // walk forward until a VAR (type‐generic) or MVAR (method‐generic) is hit
- while (elem.DataType != DATATYPE_VAR && elem.DataType != DATATYPE_MVAR)
- {
- if (FAILED(parser.Advance(elem)))
- {
- return false;
- }
- }
+ if (elem.DataType == DATATYPE_CLASS || elem.DataType == DATATYPE_VALUETYPE)
+ {
+ // consume the CLASS/VALUETYPE marker
+ if (FAILED(parser.Advance(elem)))
+ {
+ return false;
+ }
+ // consume the generic‐definition token itself
+ if (FAILED(parser.Advance(elem)))
+ {
+ return false;
+ }
+ // consume the count of generic arguments
+ if (FAILED(parser.Advance(elem)))
+ {
+ return false;
+ }
+ }
- // If it's a type‐generic slot (!T), resolve against the caller's closed generic
- if (elem.DataType == DATATYPE_VAR)
- {
- int pos = elem.GenericParamPosition;
+ // walk forward until a VAR (type‐generic) or MVAR (method‐generic) is hit
+ while (elem.DataType != DATATYPE_VAR && elem.DataType != DATATYPE_MVAR)
+ {
+ if (FAILED(parser.Advance(elem)))
+ {
+ return false;
+ }
+ }
+ }
- // Use the *caller's* bound genericType (Stack, etc.)
- if (caller == nullptr || caller->genericType == nullptr)
- {
- return false;
- }
+ // If it's a type‐generic slot (!T), resolve against the caller's closed generic
+ if (elem.DataType == DATATYPE_VAR)
+ {
+ int pos = elem.GenericParamPosition;
- auto &tsi = *caller->genericType;
- CLR_UINT32 closedTsRow = tsi.TypeSpec();
+ // Use the *caller's* bound genericType (Stack, etc.)
+ if (caller == nullptr || caller->genericType == nullptr)
+ {
+ return false;
+ }
- CLR_RT_TypeDef_Index realTypeDef;
- NanoCLRDataType realDataType;
+ auto &tsi = *caller->genericType;
+ CLR_UINT32 closedTsRow = tsi.TypeSpec();
- // Only call this once to map (e.g. !T→Int32)
- caller->assembly
- ->FindGenericParamAtTypeSpec(closedTsRow, (CLR_UINT32)pos, realTypeDef, realDataType);
+ CLR_RT_TypeDef_Index realTypeDef;
+ NanoCLRDataType realDataType;
- // populate this instance
- data = realTypeDef.data;
- assembly = g_CLR_RT_TypeSystem.m_assemblies[realTypeDef.Assembly() - 1];
- target = assembly->GetTypeDef(realTypeDef.Type());
+ // Only call this once to map (e.g. !T→Int32)
- return true;
- }
- else
- {
- // elem.DataType == DATATYPE_MVAR
+ g_CLR_RT_TypeSystem.m_assemblies[caller->genericType->Assembly() - 1]
+ ->FindGenericParamAtTypeSpec(closedTsRow, (CLR_UINT32)pos, realTypeDef, realDataType);
- // Use the *caller's* bound genericType (Stack, etc.)
- if (caller == nullptr || caller->genericType == nullptr)
- {
- return false;
- }
+ // populate this instance
+ data = realTypeDef.data;
+ assembly = g_CLR_RT_TypeSystem.m_assemblies[realTypeDef.Assembly() - 1];
+ target = assembly->GetTypeDef(realTypeDef.Type());
+ }
- CLR_RT_GenericParam_Index gpIdx;
- caller->assembly->FindGenericParamAtMethodDef(*caller, elem.GenericParamPosition, gpIdx);
- auto &gp = caller->assembly->crossReferenceGenericParam[gpIdx.GenericParam()];
+ else if (elem.DataType == DATATYPE_MVAR)
+ {
+ // Use the caller bound genericType (Stack, etc.)
+ if (caller == nullptr || caller->genericType == nullptr)
+ {
+ return false;
+ }
- data = gp.classTypeDef.data;
- assembly = g_CLR_RT_TypeSystem.m_assemblies[gp.classTypeDef.Assembly() - 1];
- target = assembly->GetTypeDef(gp.classTypeDef.Type());
- return true;
+ CLR_RT_GenericParam_Index gpIdx;
+ caller->assembly->FindGenericParamAtMethodDef(*caller, elem.GenericParamPosition, gpIdx);
+
+ auto &gp = caller->assembly->crossReferenceGenericParam[gpIdx.GenericParam()];
+
+ data = gp.classTypeDef.data;
+ assembly = g_CLR_RT_TypeSystem.m_assemblies[gp.classTypeDef.Assembly() - 1];
+ target = assembly->GetTypeDef(gp.classTypeDef.Type());
+ }
+ }
}
+
+#if defined(NANOCLR_INSTANCE_NAMES)
+ name = assembly->GetString(target->name);
+#endif
+
+ return true;
}
default:
@@ -1081,6 +1167,117 @@ bool CLR_RT_TypeDef_Instance::ResolveToken(
return false;
}
+bool CLR_RT_TypeDef_Instance::ResolveNullableType(
+ CLR_UINT32 tk,
+ CLR_RT_Assembly *assm,
+ const CLR_RT_MethodDef_Instance *caller)
+{
+ NATIVE_PROFILE_CLR_CORE();
+
+ if (assm)
+ {
+ CLR_UINT32 index = CLR_DataFromTk(tk);
+
+ if (CLR_TypeFromTk(tk) != TBL_TypeSpec)
+ {
+ // not a TypeSpec, so return false
+ ClearInstance();
+ return false;
+ }
+
+ // Grab the raw signature for the IL token (e.g. !T[], List`1, etc.)
+ const CLR_RECORD_TYPESPEC *ts = assm->GetTypeSpec(index);
+ CLR_RT_SignatureParser parser;
+ parser.Initialize_TypeSpec(assm, ts);
+
+ CLR_RT_SignatureParser::Element elem;
+ if (FAILED(parser.Advance(elem)))
+ {
+ return false;
+ }
+
+ if (elem.DataType == DATATYPE_GENERICINST)
+ {
+ if (FAILED(parser.Advance(elem)))
+ {
+ return false;
+ }
+ }
+
+ if (elem.DataType != DATATYPE_VALUETYPE)
+ {
+ // If it's not a value type, we can't resolve it as a nullable type
+ ClearInstance();
+ return false;
+ }
+
+ // move to the next element in the signature
+ if (FAILED(parser.Advance(elem)))
+ {
+ return false;
+ }
+
+ // If it's a type‐generic slot (!T), resolve against the caller's closed generic
+ if (elem.DataType == DATATYPE_VAR)
+ {
+ int pos = elem.GenericParamPosition;
+
+ // Use the *caller's* bound genericType (Stack, etc.)
+ if (caller == nullptr || caller->genericType == nullptr)
+ {
+ return false;
+ }
+
+ auto &tsi = *caller->genericType;
+ CLR_UINT32 closedTsRow = tsi.TypeSpec();
+
+ CLR_RT_TypeDef_Index realTypeDef;
+ NanoCLRDataType realDataType;
+
+ // Only call this once to map (e.g. !T→Int32)
+ caller->assembly->FindGenericParamAtTypeSpec(closedTsRow, (CLR_UINT32)pos, realTypeDef, realDataType);
+
+ // populate this instance
+ data = realTypeDef.data;
+ assembly = g_CLR_RT_TypeSystem.m_assemblies[realTypeDef.Assembly() - 1];
+ target = assembly->GetTypeDef(realTypeDef.Type());
+
+ return true;
+ }
+ else if (elem.DataType == DATATYPE_MVAR)
+ {
+ // Use the *caller's* bound genericType (Stack, etc.)
+ if (caller == nullptr || caller->genericType == nullptr)
+ {
+ return false;
+ }
+
+ CLR_RT_GenericParam_Index gpIdx;
+ caller->assembly->FindGenericParamAtMethodDef(*caller, elem.GenericParamPosition, gpIdx);
+ auto &gp = caller->assembly->crossReferenceGenericParam[gpIdx.GenericParam()];
+
+ data = gp.classTypeDef.data;
+ assembly = g_CLR_RT_TypeSystem.m_assemblies[gp.classTypeDef.Assembly() - 1];
+ target = assembly->GetTypeDef(gp.classTypeDef.Type());
+
+ return true;
+ }
+ else
+ {
+ // If it's a class or value type, resolve the type
+ data = elem.Class.data;
+ assembly = g_CLR_RT_TypeSystem.m_assemblies[elem.Class.Assembly() - 1];
+ target = assembly->GetTypeDef(elem.Class.Type());
+
+ return true;
+ }
+ }
+
+ ClearInstance();
+
+ return false;
+}
+
//--//
bool CLR_RT_TypeDef_Instance::SwitchToParent()
@@ -1161,7 +1358,10 @@ void CLR_RT_FieldDef_Instance::ClearInstance()
genericType = nullptr;
}
-bool CLR_RT_FieldDef_Instance::ResolveToken(CLR_UINT32 tk, CLR_RT_Assembly *assm)
+bool CLR_RT_FieldDef_Instance::ResolveToken(
+ CLR_UINT32 tk,
+ CLR_RT_Assembly *assm,
+ const CLR_RT_MethodDef_Instance *caller)
{
NATIVE_PROFILE_CLR_CORE();
@@ -1191,24 +1391,41 @@ bool CLR_RT_FieldDef_Instance::ResolveToken(CLR_UINT32 tk, CLR_RT_Assembly *assm
case TBL_TypeSpec:
{
- // Field on a generic‐instantiated type.
- // Use the MDP TypeSpec (which is already the closed generic),
- genericType = &assm->crossReferenceFieldRef[index].genericType;
+ // the metadata own (possibly open) TypeSpec...
+ const CLR_RT_TypeSpec_Index *mdTS = &assm->crossReferenceFieldRef[index].genericType;
- // Look up the actual FieldDef within that closed type
- CLR_RT_FieldDef_Index resolvedField;
- if (!assm->FindFieldDef(genericType, assm->GetString(fr->name), assm, fr->signature, resolvedField))
+ // decide whether to prefer the caller’s closed-generic
+ const CLR_RT_TypeSpec_Index *effectiveTS = mdTS;
+ if (caller && caller->genericType && NANOCLR_INDEX_IS_VALID(*caller->genericType))
+ {
+ CLR_RT_TypeSpec_Instance instCaller, instMd;
+ if (instCaller.InitializeFromIndex(*caller->genericType) && instMd.InitializeFromIndex(*mdTS))
+ {
+ // check if generic definition token is the same...
+ if (instCaller.genericTypeDef.data == instMd.genericTypeDef.data)
+ {
+ // it is, therefore use the caller closed TypeSpec
+ effectiveTS = caller->genericType;
+ }
+ }
+ }
+
+ // now bind against effectiveTS
+ genericType = effectiveTS;
+
+ CLR_RT_FieldDef_Index resolved;
+
+ if (!assm->FindFieldDef(genericType, assm->GetString(fr->name), assm, fr->signature, resolved))
{
return false;
}
- // Bind to that real FieldDef
- Set(assm->assemblyIndex, resolvedField.Field());
+ data = resolved.data;
assembly = assm;
target = assembly->GetFieldDef(Field());
+
break;
}
-
default:
// should not happen
return false;
@@ -1289,6 +1506,15 @@ bool CLR_RT_MethodDef_Instance::InitializeFromIndex(
return false;
}
+ // if this is a generic type, need to advance to the next
+ if (elem.DataType == DATATYPE_GENERICINST)
+ {
+ if (FAILED(parser.Advance(elem)))
+ {
+ return false;
+ }
+ }
+
CLR_RT_TypeDef_Index ownerTypeIdx;
CLR_RT_MethodDef_Index mdRebound;
@@ -1373,13 +1599,18 @@ bool CLR_RT_MethodDef_Instance::ResolveToken(
if (callerInst.InitializeFromIndex(*callerGeneric))
{
CLR_RT_SignatureParser parserCaller;
- parserCaller.Initialize_TypeSpec(callerInst.assembly, callerInst.target);
+ parserCaller.Initialize_TypeSpec(callerInst);
CLR_RT_SignatureParser::Element elemCaller;
// advance to the generic instance which will point to the class
parserCaller.Advance(elemCaller);
+ if (elemCaller.DataType == DATATYPE_GENERICINST)
+ {
+ parserCaller.Advance(elemCaller);
+ }
+
CLR_UINT32 callerTypeDefToken = elemCaller.Class.data;
// parse the MethodRef declared TypeSpec
@@ -1387,16 +1618,21 @@ bool CLR_RT_MethodDef_Instance::ResolveToken(
if (ownerInst.InitializeFromIndex(*methodOwnerTS))
{
CLR_RT_SignatureParser parserOwner;
- parserOwner.Initialize_TypeSpec(ownerInst.assembly, ownerInst.target);
+ parserOwner.Initialize_TypeSpec(ownerInst);
CLR_RT_SignatureParser::Element elemOwner;
// advance to the generic instance which will point to the class
parserOwner.Advance(elemOwner);
+ if (elemOwner.DataType == DATATYPE_GENERICINST)
+ {
+ parserOwner.Advance(elemOwner);
+ }
+
CLR_UINT32 ownerTypeDefToken = elemOwner.Class.data;
- if (callerTypeDefToken == ownerTypeDefToken)
+ if ((callerTypeDefToken == ownerTypeDefToken) && callerTypeDefToken != 0x0)
{
// we have a match on the typeDef, so they refer to the same type
// lets bind using the closed generic
@@ -1410,17 +1646,16 @@ bool CLR_RT_MethodDef_Instance::ResolveToken(
const CLR_RT_TypeSpec_Index *definitiveTypeSpec = useCaller ? callerGeneric : methodOwnerTS;
genericType = (CLR_RT_TypeSpec_Index *)definitiveTypeSpec;
- CLR_INDEX tsAsmIdx = genericType->Assembly();
- CLR_RT_Assembly *genericTypeAssembly = g_CLR_RT_TypeSystem.m_assemblies[tsAsmIdx - 1];
+ CLR_RT_Assembly *methodAssembly = g_CLR_RT_TypeSystem.m_assemblies[methodOwnerTS->Assembly() - 1];
- const CLR_RECORD_TYPESPEC *ts = genericTypeAssembly->GetTypeSpec(definitiveTypeSpec->TypeSpec());
+ const CLR_RECORD_TYPESPEC *ts = methodAssembly->GetTypeSpec(methodOwnerTS->TypeSpec());
CLR_UINT32 assemblyIndex = 0xFFFF;
CLR_RT_MethodDef_Index methodIndex;
- if (!genericTypeAssembly->FindMethodDef(
+ if (!methodAssembly->FindMethodDef(
ts,
- genericTypeAssembly->GetString(mr->name),
- genericTypeAssembly,
+ methodAssembly->GetString(mr->name),
+ methodAssembly,
mr->signature,
methodIndex,
assemblyIndex))
@@ -1577,13 +1812,36 @@ bool CLR_RT_MethodDef_Instance::GetDeclaringType(CLR_RT_TypeDef_Instance &declTy
CLR_RT_SignatureParser::Element elem;
parser.Advance(elem);
- return declType.InitializeFromIndex(elem.Class);
+ if (elem.DataType == DATATYPE_GENERICINST)
+ {
+ // generic type, advance again to get the type
+ parser.Advance(elem);
+
+ return declType.InitializeFromIndex(elem.Class);
+ }
+ else if (elem.DataType == DATATYPE_VAR)
+ {
+ // generic type, advance to get the type
+ int pos = elem.GenericParamPosition;
+ // Use the *caller's* bound genericType (Stack, etc.)
+ CLR_RT_TypeDef_Index td;
+ NanoCLRDataType dt;
+ if (tsAsm == nullptr ||
+ tsAsm->FindGenericParamAtTypeSpec(genericType->TypeSpec(), (CLR_UINT32)pos, td, dt) == false)
+ {
+ return false;
+ }
+
+ return declType.InitializeFromIndex(td);
+ }
}
else
{
// Normal (non‐generic or open‐generic)
return declType.InitializeFromMethod(*this);
}
+
+ return false;
}
//////////////////////////////
@@ -1863,10 +2121,10 @@ HRESULT CLR_RT_TypeDescriptor::InitializeFromGenericType(const CLR_RT_TypeSpec_I
}
else
{
- m_flags = CLR_RT_DataTypeLookup::c_ManagedType | CLR_RT_DataTypeLookup::c_GenericInstance;
+ m_flags = CLR_RT_DataTypeLookup::c_ManagedType;
- m_reflex.kind = REFLECTION_GENERICTYPE;
- m_reflex.data.genericType = m_handlerGenericType;
+ m_reflex.kind = REFLECTION_TYPESPEC;
+ m_reflex.data.typeSpec = m_handlerGenericType;
}
m_handlerCls.ClearInstance();
@@ -2036,7 +2294,6 @@ HRESULT CLR_RT_TypeDescriptor::InitializeFromObject(const CLR_RT_HeapBlock &ref)
{
const CLR_RT_TypeDef_Index *cls = nullptr;
const CLR_RT_ReflectionDef_Index *reflex = nullptr;
- const CLR_RT_TypeSpec_Index *genericType = nullptr;
switch (dt)
{
@@ -2100,6 +2357,12 @@ HRESULT CLR_RT_TypeDescriptor::InitializeFromObject(const CLR_RT_HeapBlock &ref)
case REFLECTION_FIELD:
cls = &g_CLR_RT_WellKnownTypes.FieldInfo;
break;
+ case REFLECTION_GENERICTYPE:
+ cls = &g_CLR_RT_WellKnownTypes.Type;
+ break;
+ case REFLECTION_TYPESPEC:
+ cls = &g_CLR_RT_WellKnownTypes.Type;
+ break;
}
break;
@@ -2123,10 +2386,6 @@ HRESULT CLR_RT_TypeDescriptor::InitializeFromObject(const CLR_RT_HeapBlock &ref)
}
break;
- case DATATYPE_GENERICINST:
- genericType = &obj->ObjectGenericType();
- break;
-
//--//
default:
@@ -2143,11 +2402,6 @@ HRESULT CLR_RT_TypeDescriptor::InitializeFromObject(const CLR_RT_HeapBlock &ref)
m_reflex = *reflex;
}
- if (genericType)
- {
- NANOCLR_CHECK_HRESULT(InitializeFromGenericType(*genericType));
- }
-
if (dt == DATATYPE_SZARRAY)
{
ConvertToArray();
@@ -2276,7 +2530,7 @@ HRESULT CLR_RT_TypeDescriptor::ExtractTypeIndexFromObject(const CLR_RT_HeapBlock
if (desc.GetDataType() == DATATYPE_GENERICINST)
{
- res.Set(desc.m_handlerGenericType.Assembly(), desc.m_handlerGenericType.typeDefIndex);
+ res.data = desc.m_handlerGenericType.genericTypeDef.data;
}
else
{
@@ -4290,6 +4544,7 @@ static const TypeIndexLookup c_TypeIndexLookup[] = {
TIL("System", "Object", Object),
TIL("System", "ValueType", ValueType),
TIL("System", "Enum", Enum),
+ TIL("System", "Nullable`1", Nullable),
TIL("System", "AppDomainUnloadedException", AppDomainUnloadedException),
TIL("System", "ArgumentNullException", ArgumentNullException),
@@ -4778,6 +5033,12 @@ bool CLR_RT_Assembly::FindGenericParamAtTypeSpec(
return false;
}
+ // move to type
+ if (FAILED(parser.Advance(element)))
+ {
+ return false;
+ }
+
// sanity check for invalid parameter position
if (genericParameterPosition > parser.GenParamCount)
{
@@ -4925,27 +5186,40 @@ bool CLR_RT_Assembly::FindFieldDef(
{
NATIVE_PROFILE_CLR_CORE();
+ // find assembly of TypeSpec
+ CLR_RT_Assembly *assm = g_CLR_RT_TypeSystem.m_assemblies[tsIndex->Assembly() - 1];
+
CLR_RT_SignatureParser parser;
- parser.Initialize_TypeSpec(base, base->GetTypeSpec(tsIndex->TypeSpec()));
+ parser.Initialize_TypeSpec(assm, assm->GetTypeSpec(tsIndex->TypeSpec()));
CLR_RT_SignatureParser::Element element;
// get type
parser.Advance(element);
+ CLR_RT_TypeDef_Index typeDef{};
+ CLR_RT_TypeDef_Instance typeDefInstance{};
+ const char *typeName;
+
// if this is a generic type, need to advance to get type
if (element.DataType == DATATYPE_GENERICINST)
{
parser.Advance(element);
+
+ // OK to set the data directly
+ typeDef.data = element.Class.data;
}
+ else if (element.DataType == DATATYPE_VAR)
+ {
+ // resolve the !T against the *closed* typeIndex
+ CLR_RT_TypeSpec_Instance typeSpecInstance;
+ typeSpecInstance.InitializeFromIndex(*tsIndex);
- CLR_RT_TypeDef_Index typeDef;
- typeDef.data = element.Class.data;
+ typeDef.data = typeSpecInstance.genericTypeDef.data;
+ }
- CLR_RT_TypeDef_Instance typeDefInstance;
typeDefInstance.InitializeFromIndex(typeDef);
-
- const char *typeName = GetString(typeDefInstance.target->name);
+ typeName = GetString(typeDefInstance.target->name);
const CLR_RECORD_FIELDDEF *fd = GetFieldDef(0);
@@ -5042,33 +5316,13 @@ bool CLR_RT_Assembly::FindMethodDef(
return false;
}
- CLR_RT_TypeSpec_Instance tsInstance;
+ CLR_RT_TypeSpec_Instance tsInstance{};
if (!tsInstance.InitializeFromIndex(tsIndex))
{
index.Clear();
return false;
}
- // switch to the assembly that declared this TypeSpec
- CLR_RT_Assembly *declAssm = tsInstance.assembly;
-
- CLR_INDEX typeDefIdx = tsInstance.typeDefIndex;
-
- // validate that it really is in-range
- if (typeDefIdx >= declAssm->tablesSize[TBL_TypeDef])
- {
- // doesn't seem to be, jump to TypeSpec parsing
- goto try_typespec;
- }
-
- if (declAssm->FindMethodDef(declAssm->GetTypeDef(typeDefIdx), methodName, base, sig, index))
- {
- assmIndex = declAssm->assemblyIndex;
- return true;
- }
-
-try_typespec:
-
// parse the TypeSpec signature to get the *definition* token of the generic type:
CLR_RT_SignatureParser parser{};
parser.Initialize_TypeSpec(this, ts);
@@ -5080,6 +5334,15 @@ bool CLR_RT_Assembly::FindMethodDef(
return false;
}
+ // if this is a generic type, need the type
+ if (elem.DataType == DATATYPE_GENERICINST)
+ {
+ if (FAILED(parser.Advance(elem)))
+ {
+ return false;
+ }
+ }
+
CLR_UINT32 genericDefToken = elem.Class.data;
CLR_RT_TypeDef_Index typeDef;
@@ -6201,10 +6464,40 @@ bool CLR_RT_TypeSystem::MatchSignatureElement(
return false;
}
- if ((resLeft.DataType == DATATYPE_VAR && resRight.DataType == DATATYPE_VAR) &&
- (resLeft.GenericParamPosition != resRight.GenericParamPosition))
+ if (resLeft.DataType == DATATYPE_VAR && resRight.DataType == DATATYPE_VAR)
{
- return false;
+ if (resLeft.GenericParamPosition != resRight.GenericParamPosition)
+ {
+ return false;
+ }
+ else
+ {
+ if (parserLeft.IsGenericInst && parserRight.IsGenericInst)
+ {
+ // TODO: we can do better here by checking the actual type of the generic parameters
+ // CLR_RT_TypeDef_Index leftTypeDef;
+ // NanoCLRDataType leftDT;
+ // CLR_RT_TypeDef_Index rightTypeDef;
+ // NanoCLRDataType rightDT;
+
+ // parserLeft.Assembly->FindGenericParamAtTypeSpec(
+ // resLeft.TypeSpec.TypeSpec(),
+ // resLeft.GenericParamPosition,
+ // leftTypeDef,
+ // leftDT);
+
+ // parserRight.Assembly->FindGenericParamAtTypeSpec(
+ // resRight.TypeSpec.TypeSpec(),
+ // resRight.GenericParamPosition,
+ // rightTypeDef,
+ // rightDT);
+
+ // if (leftTypeDef.data != rightTypeDef.data || leftDT != rightDT)
+ //{
+ // return false;
+ // }
+ }
+ }
}
if (parserLeft.IsGenericInst != parserRight.IsGenericInst)
@@ -6214,27 +6507,65 @@ bool CLR_RT_TypeSystem::MatchSignatureElement(
if (parserLeft.IsGenericInst || parserRight.IsGenericInst)
{
- if (resLeft.GenericParamPosition == 0xFFFF && resRight.GenericParamPosition == 0xFFFF)
+ if (resLeft.DataType == DATATYPE_GENERICINST && resRight.DataType == DATATYPE_GENERICINST)
{
+ // processing generic instance signature
+ // need to advance to get generic type and param count
+ if (FAILED(parserLeft.Advance(resLeft)) || FAILED(parserRight.Advance(resRight)))
+ {
+ return false;
+ }
+
// need to check if type of generic parameters match, if there are more
if (parserLeft.ParamCount > 0 && parserRight.ParamCount > 0)
{
- if (FAILED(parserLeft.Advance(resLeft)) || FAILED(parserRight.Advance(resRight)))
+ if (parserLeft.ParamCount != parserRight.ParamCount)
{
return false;
}
- }
- if (resLeft.DataType != resRight.DataType)
- {
- return false;
+ if (resLeft.DataType != resRight.DataType)
+ {
+ return false;
+ }
}
}
- else if (resLeft.GenericParamPosition != resRight.GenericParamPosition)
+ else
{
- return false;
+ if (parserLeft.GenParamCount != parserRight.GenParamCount)
+ {
+ return false;
+ }
+ else if (resLeft.GenericParamPosition != resRight.GenericParamPosition)
+ {
+ return false;
+ }
}
}
+
+ // if (parserLeft.IsGenericInst || parserRight.IsGenericInst)
+ //{
+ // if (resLeft.GenericParamPosition == 0xFFFF && resRight.GenericParamPosition == 0xFFFF)
+ // {
+ // // need to check if type of generic parameters match, if there are more
+ // if (parserLeft.ParamCount > 0 && parserRight.ParamCount > 0)
+ // {
+ // if (FAILED(parserLeft.Advance(resLeft)) || FAILED(parserRight.Advance(resRight)))
+ // {
+ // return false;
+ // }
+ // }
+
+ // if (resLeft.DataType != resRight.DataType)
+ // {
+ // return false;
+ // }
+ // }
+ // else if (resLeft.GenericParamPosition != resRight.GenericParamPosition)
+ // {
+ // return false;
+ // }
+ //}
}
return true;
@@ -6271,22 +6602,28 @@ HRESULT CLR_RT_TypeSystem::BuildTypeName(
NATIVE_PROFILE_CLR_CORE();
NANOCLR_HEADER();
- CLR_RT_TypeSpec_Instance instance;
+ CLR_RT_TypeSpec_Instance typeSpecInstance;
bool closeGenericSignature = false;
- if (instance.InitializeFromIndex(typeIndex) == false)
+ if (typeSpecInstance.InitializeFromIndex(typeIndex) == false)
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
CLR_RT_SignatureParser parser;
- parser.Initialize_TypeSpec(instance.assembly, instance.assembly->GetTypeSpec(typeIndex.TypeSpec()));
+ parser.Initialize_TypeSpec(typeSpecInstance);
CLR_RT_SignatureParser::Element element;
// get type
parser.Advance(element);
+ // if this is a generic type, need to advance to get type
+ if (element.DataType == DATATYPE_GENERICINST)
+ {
+ parser.Advance(element);
+ }
+
CLR_RT_TypeDef_Index typeDef;
typeDef.data = element.Class.data;
@@ -6311,7 +6648,7 @@ HRESULT CLR_RT_TypeSystem::BuildTypeName(
NanoCLRDataType realDt;
// this will bind !T→System.Int32, etc.
- instance.assembly->FindGenericParamAtTypeSpec(
+ typeSpecInstance.assembly->FindGenericParamAtTypeSpec(
typeIndex.TypeSpec(), // closed instantiation row
element.GenericParamPosition, // the !N slot
realTd,
@@ -6446,7 +6783,7 @@ HRESULT CLR_RT_TypeSystem::BuildMethodName(
if (tsInst.InitializeFromIndex(*genericType))
{
- if (tsInst.typeDefIndex == declTypeIdx.Type())
+ if (tsInst.genericTypeDef.Type() == declTypeIdx.Type())
{
useGeneric = true;
}
@@ -6460,6 +6797,13 @@ HRESULT CLR_RT_TypeSystem::BuildMethodName(
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
+
+ if (instOwner.InitializeFromMethod(inst) == false)
+ {
+ NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
+ }
+
+ NANOCLR_CHECK_HRESULT(BuildTypeName(instOwner, szBuffer, iBuffer));
}
else
{
@@ -6468,15 +6812,10 @@ HRESULT CLR_RT_TypeSystem::BuildMethodName(
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
- }
- if (instOwner.InitializeFromMethod(inst) == false)
- {
- NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
+ NANOCLR_CHECK_HRESULT(BuildTypeName(*genericType, szBuffer, iBuffer, 0));
}
- NANOCLR_CHECK_HRESULT(BuildTypeName(instOwner, szBuffer, iBuffer));
-
CLR_SafeSprintf(szBuffer, iBuffer, "::%s", inst.assembly->GetString(inst.target->name));
NANOCLR_NOCLEANUP();
diff --git a/src/CLR/Diagnostics/Diagnostics_stub.cpp b/src/CLR/Diagnostics/Diagnostics_stub.cpp
index d543cd753d..2ca278ea77 100644
--- a/src/CLR/Diagnostics/Diagnostics_stub.cpp
+++ b/src/CLR/Diagnostics/Diagnostics_stub.cpp
@@ -112,7 +112,7 @@ __nfweak const CLR_UINT8 *CLR_SkipBodyOfOpcodeCompressed(const CLR_UINT8 *ip, CL
#if defined(NANOCLR_TRACE_INSTRUCTIONS)
-__nfweak void CLR_RT_Assembly::DumpToken(CLR_UINT32 tk, const CLR_RT_TypeSpec_Index *genericType)
+__nfweak void CLR_RT_Assembly::DumpToken(CLR_UINT32 tk, const CLR_RT_MethodDef_Instance &methodDefInstance)
{
NATIVE_PROFILE_CLR_DIAGNOSTICS();
}
diff --git a/src/CLR/Diagnostics/Info.cpp b/src/CLR/Diagnostics/Info.cpp
index 6a703cd098..68b2a8a8ce 100644
--- a/src/CLR/Diagnostics/Info.cpp
+++ b/src/CLR/Diagnostics/Info.cpp
@@ -413,7 +413,7 @@ const CLR_UINT8 *CLR_SkipBodyOfOpcodeCompressed(const CLR_UINT8 *ip, CLR_OPCODE
#if defined(NANOCLR_TRACE_INSTRUCTIONS)
-void CLR_RT_Assembly::DumpToken(CLR_UINT32 token, const CLR_RT_TypeSpec_Index *genericType)
+void CLR_RT_Assembly::DumpToken(CLR_UINT32 token, const CLR_RT_MethodDef_Instance &methodDefInstance)
{
NATIVE_PROFILE_CLR_DIAGNOSTICS();
CLR_UINT32 index = CLR_DataFromTk(token);
@@ -447,12 +447,12 @@ void CLR_RT_Assembly::DumpToken(CLR_UINT32 token, const CLR_RT_TypeSpec_Index *g
const auto &xref = crossReferenceFieldRef[index];
// If the caller passed in a closed‐generic TypeSpec, use that …
- if (genericType != nullptr && genericType->data != CLR_EmptyToken)
+ if (methodDefInstance.genericType != nullptr && methodDefInstance.genericType->data != CLR_EmptyToken)
{
// Build the closed‐generic owner name
char rgType[256], *sz = rgType;
size_t cb = sizeof(rgType);
- g_CLR_RT_TypeSystem.BuildTypeName(*genericType, sz, cb, 0);
+ g_CLR_RT_TypeSystem.BuildTypeName(*methodDefInstance.genericType, sz, cb, 0);
// Append the field name
CLR_SafeSprintf(sz, cb, "::%s", GetString(fr->name));
@@ -472,18 +472,18 @@ void CLR_RT_Assembly::DumpToken(CLR_UINT32 token, const CLR_RT_TypeSpec_Index *g
CLR_UINT32 idx = CLR_DataFromTk(token);
auto &xref = crossReferenceMethodRef[idx];
- // Build a MethodRef_Index so we can format the reference:
- CLR_RT_MethodRef_Index mri;
- mri.Set(assemblyIndex, idx);
+ // Build a MethodDef_Index so we can format the reference:
+ CLR_RT_MethodDef_Index mdi;
+ mdi.data = xref.target.data;
- // Decide which TypeSpec to supply to BuildMethodRefName:
- // 1) If the caller passed a non-null genericType (i.e. we’re inside SimpleList),
+ // Decide which TypeSpec to supply to BuildMethodName:
+ // 1) If the caller passed a non-null genericType (i.e. we're inside SimpleList),
// use that, so ResizeArray prints as SimpleList::ResizeArray.
// 2) Otherwise, fall back to xref.genericType (the raw MethodRef own owner).
const CLR_RT_TypeSpec_Index *ownerTypeSpec;
- if (genericType != nullptr && NANOCLR_INDEX_IS_VALID(*genericType))
+ if (methodDefInstance.genericType != nullptr && NANOCLR_INDEX_IS_VALID(*methodDefInstance.genericType))
{
- ownerTypeSpec = genericType;
+ ownerTypeSpec = methodDefInstance.genericType;
}
else
{
@@ -492,7 +492,9 @@ void CLR_RT_Assembly::DumpToken(CLR_UINT32 token, const CLR_RT_TypeSpec_Index *g
char buf[256], *p = buf;
size_t cb = sizeof(buf);
- g_CLR_RT_TypeSystem.BuildMethodRefName(mri, ownerTypeSpec, p, cb);
+
+ g_CLR_RT_TypeSystem.BuildMethodName(mdi, ownerTypeSpec, p, cb);
+
CLR_Debug::Printf("%s", buf);
break;
}
@@ -525,12 +527,12 @@ void CLR_RT_Assembly::DumpToken(CLR_UINT32 token, const CLR_RT_TypeSpec_Index *g
//
CLR_UINT32 ownerAsm = assemblyIndex;
- if (genericType != nullptr && NANOCLR_INDEX_IS_VALID(*genericType))
+ if (methodDefInstance.genericType != nullptr && NANOCLR_INDEX_IS_VALID(*methodDefInstance.genericType))
{
- ownerAsm = genericType->Assembly();
+ ownerAsm = methodDefInstance.genericType->Assembly();
}
- CLR_RT_TypeSpec_Index tsIdx;
+ CLR_RT_TypeSpec_Index tsIdx{};
tsIdx.Set(assemblyIndex, index);
// bind to get the signature blob
@@ -543,8 +545,8 @@ void CLR_RT_Assembly::DumpToken(CLR_UINT32 token, const CLR_RT_TypeSpec_Index *g
}
// start parsing the signature
- CLR_RT_SignatureParser parser;
- parser.Initialize_TypeSpec(tsInst.assembly, tsInst.target);
+ CLR_RT_SignatureParser parser{};
+ parser.Initialize_TypeSpec(tsInst);
// read first element
CLR_RT_SignatureParser::Element elem;
@@ -559,17 +561,31 @@ void CLR_RT_Assembly::DumpToken(CLR_UINT32 token, const CLR_RT_TypeSpec_Index *g
break;
}
- if (elem.DataType == DATATYPE_VAR || elem.DataType == DATATYPE_MVAR)
+ if (elem.DataType == DATATYPE_GENERICINST)
+ {
+ if (FAILED(parser.Advance(elem)))
+ {
+ // unable to bind; dump raw RID
+ CLR_Debug::Printf("[TYPESPEC:%08x]", token);
+ break;
+ }
+ }
+
+ if (elem.DataType == DATATYPE_VAR)
{
- int gpIndex = elem.GenericParamPosition;
+ int gpPosition = elem.GenericParamPosition;
// if the caller's genericType is non‐null, ask the CLR to map !n→actual argument:
- if (genericType != nullptr && NANOCLR_INDEX_IS_VALID(*genericType))
+ if (methodDefInstance.genericType != nullptr && NANOCLR_INDEX_IS_VALID(*methodDefInstance.genericType))
{
CLR_RT_TypeDef_Index tdArg{};
NanoCLRDataType dtArg;
- bool ok = g_CLR_RT_TypeSystem.m_assemblies[genericType->Assembly() - 1]
- ->FindGenericParamAtTypeSpec(genericType->TypeSpec(), gpIndex, tdArg, dtArg);
+ bool ok = g_CLR_RT_TypeSystem.m_assemblies[methodDefInstance.genericType->Assembly() - 1]
+ ->FindGenericParamAtTypeSpec(
+ methodDefInstance.genericType->TypeSpec(),
+ gpPosition,
+ tdArg,
+ dtArg);
if (ok)
{
char bufArg[256]{};
@@ -585,15 +601,47 @@ void CLR_RT_Assembly::DumpToken(CLR_UINT32 token, const CLR_RT_TypeSpec_Index *g
}
}
- // Couldn't resolve or caller was not generic: print "!n" or "!!n" literally
- if (elem.DataType == DATATYPE_VAR)
- {
- CLR_Debug::Printf("!%d", gpIndex);
- }
- else
+ // Couldn't resolve or caller was not generic: print "!n" literally
+ CLR_Debug::Printf("!%d", gpPosition);
+
+ break;
+ }
+ else if (elem.DataType == DATATYPE_MVAR)
+ {
+ int gpPosition = elem.GenericParamPosition;
+
+ // if the caller's genericType is non‐null, ask the CLR to map !n→actual argument:
+ if (methodDefInstance.genericType != nullptr && NANOCLR_INDEX_IS_VALID(*methodDefInstance.genericType))
{
- CLR_Debug::Printf("!!%d", gpIndex);
+ CLR_RT_GenericParam_Index gpIndex;
+
+ bool ok = g_CLR_RT_TypeSystem.m_assemblies[methodDefInstance.genericType->Assembly() - 1]
+ ->FindGenericParamAtMethodDef(methodDefInstance, gpPosition, gpIndex);
+ if (ok)
+ {
+ CLR_RT_GenericParam_CrossReference gp =
+ g_CLR_RT_TypeSystem.m_assemblies[methodDefInstance.genericType->Assembly() - 1]
+ ->crossReferenceGenericParam[gpIndex.GenericParam()];
+
+ char bufArg[256]{};
+ char *pArg = bufArg;
+ size_t cbArg = sizeof(bufArg);
+
+ g_CLR_RT_TypeSystem.BuildTypeName(
+ gp.classTypeDef,
+ pArg,
+ cbArg,
+ CLR_RT_TypeSystem::TYPENAME_FLAGS_FULL,
+ elem.Levels);
+
+ CLR_Debug::Printf("%s", bufArg);
+
+ break;
+ }
}
+ // Couldn't resolve or caller was not generic: print "!!n" literally
+ CLR_Debug::Printf("!!%d", gpPosition);
+
break;
}
else if (elem.DataType == DATATYPE_SZARRAY)
@@ -611,13 +659,17 @@ void CLR_RT_Assembly::DumpToken(CLR_UINT32 token, const CLR_RT_TypeSpec_Index *g
{
int gpIndex = elem.GenericParamPosition;
- if (genericType != nullptr && NANOCLR_INDEX_IS_VALID(*genericType))
+ if (methodDefInstance.genericType != nullptr &&
+ NANOCLR_INDEX_IS_VALID(*methodDefInstance.genericType))
{
CLR_RT_TypeDef_Index tdArg{};
NanoCLRDataType dtArg;
- bool genericParamFound =
- tsInst.assembly->FindGenericParamAtTypeSpec(genericType->TypeSpec(), gpIndex, tdArg, dtArg);
+ bool genericParamFound = tsInst.assembly->FindGenericParamAtTypeSpec(
+ methodDefInstance.genericType->TypeSpec(),
+ gpIndex,
+ tdArg,
+ dtArg);
if (genericParamFound)
{
// print "I4[]" or the bound argument plus []
@@ -887,12 +939,12 @@ void CLR_RT_Assembly::DumpOpcodeDirect(
else
{
// In the unlikely case ResolveToken fails, fall back to raw DumpToken:
- DumpToken(token, call.genericType);
+ DumpToken(token, call);
}
}
else
{
- DumpToken(token, call.genericType);
+ DumpToken(token, call);
}
}
else
diff --git a/src/CLR/Include/nanoCLR_Runtime.h b/src/CLR/Include/nanoCLR_Runtime.h
index e00998b737..e3d77e6608 100644
--- a/src/CLR/Include/nanoCLR_Runtime.h
+++ b/src/CLR/Include/nanoCLR_Runtime.h
@@ -843,7 +843,7 @@ struct CLR_RT_ReflectionDef_Index
CLR_RT_TypeDef_Index type;
CLR_RT_MethodDef_Index method;
CLR_RT_FieldDef_Index field;
- CLR_RT_TypeSpec_Index genericType;
+ CLR_RT_TypeSpec_Index typeSpec;
CLR_UINT32 raw;
} data;
@@ -1164,6 +1164,7 @@ struct CLR_RT_SignatureParser
static const int c_Object = 5;
static const int c_GenericParamType = 6;
static const int c_MethodSpec = 7;
+ static const int c_LocalVar = 8;
struct Element
{
@@ -1203,9 +1204,11 @@ struct CLR_RT_SignatureParser
void Initialize_TypeSpec(CLR_RT_Assembly *assm, CLR_PMETADATA ts);
void Initialize_TypeSpec(CLR_RT_Assembly *assm, const CLR_RECORD_TYPESPEC *ts);
+ void Initialize_TypeSpec(CLR_RT_TypeSpec_Instance tsInstance);
void Initialize_Interfaces(CLR_RT_Assembly *assm, const CLR_RECORD_TYPEDEF *td);
void Initialize_MethodLocals(CLR_RT_Assembly *assm, const CLR_RECORD_METHODDEF *md);
+ void Initialize_LocalVar(CLR_RT_Assembly *assm, const CLR_PMETADATA sig);
bool Initialize_GenericParamTypeSignature(CLR_RT_Assembly *assm, const CLR_RECORD_GENERICPARAM *gp);
void Initialize_FieldDef(CLR_RT_Assembly *assm, const CLR_RECORD_FIELDDEF *fd);
@@ -1564,7 +1567,7 @@ struct CLR_RT_Assembly : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCAT
DECL_POSTFIX;
private:
- void DumpToken(CLR_UINT32 tk, const CLR_RT_TypeSpec_Index *genericType) DECL_POSTFIX;
+ void DumpToken(CLR_UINT32 tk, const CLR_RT_MethodDef_Instance &methodDefInstance) DECL_POSTFIX;
void DumpSignature(CLR_SIG sig) DECL_POSTFIX;
void DumpSignature(CLR_PMETADATA &p) DECL_POSTFIX;
void DumpSignatureToken(CLR_PMETADATA &p) DECL_POSTFIX;
@@ -1691,6 +1694,7 @@ struct CLR_RT_WellKnownTypes
CLR_RT_TypeDef_Index Object;
CLR_RT_TypeDef_Index ValueType;
CLR_RT_TypeDef_Index Enum;
+ CLR_RT_TypeDef_Index Nullable;
CLR_RT_TypeDef_Index AppDomainUnloadedException;
CLR_RT_TypeDef_Index ArgumentNullException;
@@ -2082,7 +2086,7 @@ struct CLR_RT_TypeSpec_Instance : public CLR_RT_TypeSpec_Index
CLR_RT_Assembly *assembly;
const CLR_RECORD_TYPESPEC *target;
- CLR_INDEX typeDefIndex;
+ CLR_RT_TypeDef_Index genericTypeDef;
//--//
@@ -2114,6 +2118,7 @@ struct CLR_RT_TypeDef_Instance : public CLR_RT_TypeDef_Index
void ClearInstance();
bool ResolveToken(CLR_UINT32 tk, CLR_RT_Assembly *assm, const CLR_RT_MethodDef_Instance *caller = nullptr);
+ bool ResolveNullableType(CLR_UINT32 tk, CLR_RT_Assembly *assm, const CLR_RT_MethodDef_Instance *caller = nullptr);
//--//
@@ -2146,7 +2151,7 @@ struct CLR_RT_FieldDef_Instance : public CLR_RT_FieldDef_Index
bool InitializeFromIndex(const CLR_RT_FieldDef_Index &index);
void ClearInstance();
- bool ResolveToken(CLR_UINT32 tk, CLR_RT_Assembly *assm);
+ bool ResolveToken(CLR_UINT32 tk, CLR_RT_Assembly *assm, const CLR_RT_MethodDef_Instance *caller);
//--//
@@ -4040,23 +4045,36 @@ struct CLR_RT_ExecutionEngine
void PutInProperList(CLR_RT_Thread *th);
CLR_INT32 GetNextThreadId();
- HRESULT InitializeReference(CLR_RT_HeapBlock &ref, CLR_RT_SignatureParser &parser);
- HRESULT InitializeReference(CLR_RT_HeapBlock &ref, const CLR_RECORD_FIELDDEF *target, CLR_RT_Assembly *assm);
+ HRESULT InitializeReference(
+ CLR_RT_HeapBlock &ref,
+ CLR_RT_SignatureParser &parser,
+ const CLR_RT_TypeSpec_Instance *genericInstance = nullptr);
+ HRESULT InitializeReference(
+ CLR_RT_HeapBlock &ref,
+ const CLR_RECORD_FIELDDEF *target,
+ CLR_RT_Assembly *assm,
+ const CLR_RT_TypeSpec_Instance *genericInstance = nullptr);
HRESULT InitializeLocals(CLR_RT_HeapBlock *locals, const CLR_RT_MethodDef_Instance &methodDefInstance);
- HRESULT NewObjectFromIndex(CLR_RT_HeapBlock &reference, const CLR_RT_TypeDef_Index &cls);
- HRESULT NewObject(CLR_RT_HeapBlock &reference, const CLR_RT_TypeDef_Instance &inst);
+ HRESULT NewObjectFromIndex(
+ CLR_RT_HeapBlock &reference,
+ const CLR_RT_TypeDef_Index &cls,
+ const CLR_RT_TypeSpec_Instance *genericInstance = nullptr);
+ HRESULT NewObject(
+ CLR_RT_HeapBlock &reference,
+ const CLR_RT_TypeDef_Instance &inst,
+ const CLR_RT_TypeSpec_Instance *genericInstance = nullptr);
HRESULT NewObject(CLR_RT_HeapBlock &reference, CLR_UINT32 token, CLR_RT_Assembly *assm);
HRESULT NewGenericInstanceObject(
CLR_RT_HeapBlock &reference,
const CLR_RT_TypeDef_Instance &typeDef,
- const CLR_RT_TypeSpec_Index &genericType);
+ const CLR_RT_TypeSpec_Index *genericType);
HRESULT NewGenericInstanceObject(
CLR_RT_HeapBlock &reference,
const CLR_RT_TypeDef_Instance &typeDef,
- CLR_RT_TypeSpec_Instance &genericInstance);
+ const CLR_RT_TypeSpec_Instance *genericInstance);
HRESULT CloneObject(CLR_RT_HeapBlock &reference, const CLR_RT_HeapBlock &source);
HRESULT CopyValueType(CLR_RT_HeapBlock *destination, const CLR_RT_HeapBlock *source);
diff --git a/src/CLR/Include/nanoCLR_Runtime__HeapBlock.h b/src/CLR/Include/nanoCLR_Runtime__HeapBlock.h
index 1498c409dc..dc926e9f43 100644
--- a/src/CLR/Include/nanoCLR_Runtime__HeapBlock.h
+++ b/src/CLR/Include/nanoCLR_Runtime__HeapBlock.h
@@ -114,7 +114,7 @@ struct CLR_RT_HeapBlock
static const CLR_UINT32 HB_Event = 0x04;
static const CLR_UINT32 HB_Pinned = 0x08;
static const CLR_UINT32 HB_Boxed = 0x10;
- static const CLR_UINT32 HB_Unused20 = 0x20;
+ static const CLR_UINT32 HB_GenericInstance = 0x20;
// If more bits are needed, HB_Signaled and HB_SignalAutoReset can be freed for use with a little work.
// It is not necessary that any heapblock can be waited upon. Currently, only Threads (Thread.Join),
// ManualResetEvent, and AutoResetEvent are waitable objects.
@@ -1084,6 +1084,11 @@ struct CLR_RT_HeapBlock
return false;
}
+ bool IsAGenericInstance() const
+ {
+ return ((DataFlags() & CLR_RT_HeapBlock::HB_GenericInstance) == CLR_RT_HeapBlock::HB_GenericInstance);
+ }
+
bool SameHeader(const CLR_RT_HeapBlock &right) const
{
return this->m_data.numeric.u8 == right.m_data.numeric.u8;
@@ -1192,10 +1197,10 @@ struct CLR_RT_HeapBlock
const CLR_RT_TypeSpec_Index &ObjectGenericType() const
{
- return m_data.genericInstance.genericType;
+ return m_data.reflection.data.typeSpec;
}
- HRESULT SetGenericInstanceObject(const CLR_RT_TypeSpec_Index &genericType);
+ HRESULT SetGenericInstanceType(const CLR_RT_TypeSpec_Index &genericType);
//--//
@@ -1347,7 +1352,7 @@ struct CLR_RT_HeapBlock
HRESULT SetReflection(const CLR_RT_ReflectionDef_Index &reflex);
HRESULT SetReflection(const CLR_RT_Assembly_Index &assm);
- HRESULT SetReflection(const CLR_RT_TypeSpec_Instance &tsInst, const CLR_RT_TypeSpec_Index *caller);
+ HRESULT SetReflection(const CLR_RT_TypeSpec_Index &typeSpec);
HRESULT SetReflection(const CLR_RT_TypeDef_Index &cls);
HRESULT SetReflection(const CLR_RT_FieldDef_Index &fd);
HRESULT SetReflection(const CLR_RT_MethodDef_Index &md);
diff --git a/src/CLR/Include/nanoCLR_Types.h b/src/CLR/Include/nanoCLR_Types.h
index c9607d3457..666106a2cc 100644
--- a/src/CLR/Include/nanoCLR_Types.h
+++ b/src/CLR/Include/nanoCLR_Types.h
@@ -530,6 +530,7 @@ enum CLR_ReflectionType
REFLECTION_METHOD = 0x05,
REFLECTION_FIELD = 0x06,
REFLECTION_GENERICTYPE = 0x07,
+ REFLECTION_TYPESPEC = 0x08,
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/System.Device.Spi/sys_dev_spi_native_System_Device_Spi_SpiDevice.cpp b/src/System.Device.Spi/sys_dev_spi_native_System_Device_Spi_SpiDevice.cpp
index c8958a14dd..d96468594d 100644
--- a/src/System.Device.Spi/sys_dev_spi_native_System_Device_Spi_SpiDevice.cpp
+++ b/src/System.Device.Spi/sys_dev_spi_native_System_Device_Spi_SpiDevice.cpp
@@ -9,7 +9,7 @@
// define this type here to make it shorter and improve code readability
typedef Library_sys_dev_spi_native_System_Device_Spi_SpiConnectionSettings SpiConnectionSettings;
-typedef Library_corlib_native_System_SpanByte SpanByte;
+typedef Library_corlib_native_System_Span_1 Span;
void System_Device_nano_spi_callback(int busIndex)
{
@@ -82,8 +82,6 @@ HRESULT Library_sys_dev_spi_native_System_Device_Spi_SpiDevice::NativeTransfer(
uint8_t *readData = nullptr;
int16_t writeSize = 0;
int16_t readSize = 0;
- int16_t readOffset = 0;
- int16_t writeOffset = 0;
SPI_WRITE_READ_SETTINGS rws;
uint32_t deviceId;
@@ -139,16 +137,12 @@ HRESULT Library_sys_dev_spi_native_System_Device_Spi_SpiDevice::NativeTransfer(
if (writeSpanByte != nullptr)
{
// get buffer
- writeBuffer = writeSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ writeBuffer = writeSpanByte[Span::FIELD___array].DereferenceArray();
if (writeBuffer != nullptr)
{
- // Get the write offset, only the elements defined by the span must be written, not the whole
- // array
- writeOffset = writeSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
-
// use the span length as write size, only the elements defined by the span must be written
- writeSize = writeSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
- writeData = (unsigned char *)writeBuffer->GetElement(writeOffset);
+ writeSize = writeSpanByte[Span::FIELD___length].NumericByRef().s4;
+ writeData = (unsigned char *)writeBuffer->GetFirstElement();
// pin the buffer
writeBuffer->Pin();
@@ -165,15 +159,12 @@ HRESULT Library_sys_dev_spi_native_System_Device_Spi_SpiDevice::NativeTransfer(
if (readSpanByte != nullptr)
{
// get buffer
- readBuffer = readSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ readBuffer = readSpanByte[Span::FIELD___array].DereferenceArray();
if (readBuffer != nullptr)
{
- // Get the read offset, only the elements defined by the span must be read, not the whole array
- readOffset = readSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
-
// use the span length as read size, only the elements defined by the span must be read
- readSize = readSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
- readData = (unsigned char *)readBuffer->GetElement(readOffset);
+ readSize = readSpanByte[Span::FIELD___length].NumericByRef().s4;
+ readData = (unsigned char *)readBuffer->GetFirstElement();
// pin the buffer
readBuffer->Pin();
diff --git a/src/nanoFramework.System.IO.Hashing/nf_sys_io_hashing_System_IO_Hashing_Crc32_stubs.cpp b/src/nanoFramework.System.IO.Hashing/nf_sys_io_hashing_System_IO_Hashing_Crc32_stubs.cpp
index 645a87fae1..7d06053ea8 100644
--- a/src/nanoFramework.System.IO.Hashing/nf_sys_io_hashing_System_IO_Hashing_Crc32_stubs.cpp
+++ b/src/nanoFramework.System.IO.Hashing/nf_sys_io_hashing_System_IO_Hashing_Crc32_stubs.cpp
@@ -5,7 +5,7 @@
#include "nf_sys_io_hashing.h"
-typedef Library_corlib_native_System_SpanByte SpanByte;
+typedef Library_corlib_native_System_Span_1 Span;
uint32_t ComputeCrc32(uint32_t crc, const uint8_t *buf, size_t len)
{
@@ -58,7 +58,6 @@ HRESULT Library_nf_sys_io_hashing_System_IO_Hashing_Crc32::ComputeHash___STATIC_
CLR_RT_HeapBlock_Array *buffer;
uint8_t *bufferData = nullptr;
int32_t bufferSize = 0;
- int32_t bufferOffset = 0;
uint32_t crc32 = 0;
uint32_t hash = 0;
@@ -70,14 +69,11 @@ HRESULT Library_nf_sys_io_hashing_System_IO_Hashing_Crc32::ComputeHash___STATIC_
crc32 = stack.Arg0().NumericByRef().u4;
// get buffer
- buffer = bufferSpanByte[SpanByte::FIELD___array].DereferenceArray();
-
- // Get the write offset
- bufferOffset = bufferSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
+ buffer = bufferSpanByte[Span::FIELD___array].DereferenceArray();
// use the span length as write size, only the elements defined by the span must be written
- bufferSize = bufferSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
- bufferData = buffer->GetElement(bufferOffset);
+ bufferSize = bufferSpanByte[Span::FIELD___length].NumericByRef().s4;
+ bufferData = buffer->GetFirstElement();
if (bufferSize == 0)
{
diff --git a/targets/AzureRTOS/ST/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp b/targets/AzureRTOS/ST/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
index ec6a5df500..3ed7425c61 100644
--- a/targets/AzureRTOS/ST/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
+++ b/targets/AzureRTOS/ST/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
@@ -7,7 +7,7 @@
typedef Library_sys_dev_i2c_native_System_Device_I2c_I2cConnectionSettings I2cConnectionSettings;
typedef Library_sys_dev_i2c_native_System_Device_I2c_I2cTransferResult I2cTransferResult;
-typedef Library_corlib_native_System_SpanByte SpanByte;
+typedef Library_corlib_native_System_Span_1 Span;
////////////////////////////////////////////
// declaration of the the I2C PAL structs //
@@ -406,8 +406,6 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
CLR_RT_HeapBlock *connectionSettings;
CLR_RT_HeapBlock_Array *writeBuffer = nullptr;
CLR_RT_HeapBlock_Array *readBuffer = nullptr;
- int readOffset = 0;
- int writeOffset = 0;
// get a pointer to the managed object instance and check that it's not nullptr
CLR_RT_HeapBlock *pThis = stack.This();
@@ -448,19 +446,16 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
break;
}
- // dereference the write and read SpanByte from the arguments
+ // dereference the write and read Span from the arguments
writeSpanByte = stack.Arg1().Dereference();
if (writeSpanByte != nullptr)
{
// get buffer
- writeBuffer = writeSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ writeBuffer = writeSpanByte[Span::FIELD___array].DereferenceArray();
if (writeBuffer != nullptr)
{
- // Get the write offset, only the elements defined by the span must be written, not the whole array
- writeOffset = writeSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
-
// use the span length as write size, only the elements defined by the span must be written
- palI2c->WriteSize = writeSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
+ palI2c->WriteSize = writeSpanByte[Span::FIELD___length].NumericByRef().s4;
// pin the buffer so DMA can find it where its supposed to be
writeBuffer->Pin();
@@ -477,14 +472,11 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
if (readSpanByte != nullptr)
{
// get buffer
- readBuffer = readSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ readBuffer = readSpanByte[Span::FIELD___array].DereferenceArray();
if (readBuffer != nullptr)
{
- // Get the read offset, only the elements defined by the span must be read, not the whole array
- readOffset = readSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
-
// use the span length as read size, only the elements defined by the span must be read
- palI2c->ReadSize = readSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
+ palI2c->ReadSize = readSpanByte[Span::FIELD___length].NumericByRef().s4;
// pin the buffer so DMA can find it where its supposed to be
readBuffer->Pin();
@@ -527,7 +519,7 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
if (writeBuffer != nullptr)
{
// grab the pointer to the array by starting and the offset specified in the span
- palI2c->WriteBuffer = (uint8_t *)writeBuffer->GetElement(writeOffset);
+ palI2c->WriteBuffer = (uint8_t *)writeBuffer->GetFirstElement();
// flush DMA buffer to ensure cache coherency
// (only required for Cortex-M7)
@@ -537,7 +529,7 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
if (readBuffer != nullptr)
{
// grab the pointer to the array by starting and the offset specified in the span
- palI2c->ReadBuffer = (uint8_t *)readBuffer->GetElement(readOffset);
+ palI2c->ReadBuffer = (uint8_t *)readBuffer->GetFirstElement();
}
// because the bus access is shared, acquire the appropriate bus
diff --git a/targets/AzureRTOS/SiliconLabs/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp b/targets/AzureRTOS/SiliconLabs/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
index 43547f50b9..81e5e7372f 100644
--- a/targets/AzureRTOS/SiliconLabs/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
+++ b/targets/AzureRTOS/SiliconLabs/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
@@ -7,7 +7,7 @@
typedef Library_sys_dev_i2c_native_System_Device_I2c_I2cConnectionSettings I2cConnectionSettings;
typedef Library_sys_dev_i2c_native_System_Device_I2c_I2cTransferResult I2cTransferResult;
-typedef Library_corlib_native_System_SpanByte SpanByte;
+typedef Library_corlib_native_System_Span_1 Span;
////////////////////////////////////////////
// declaration of the the I2C PAL structs //
@@ -412,8 +412,6 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
CLR_RT_HeapBlock *connectionSettings;
CLR_RT_HeapBlock_Array *writeBuffer = nullptr;
CLR_RT_HeapBlock_Array *readBuffer = nullptr;
- int readOffset = 0;
- int writeOffset = 0;
I2C_TransferSeq_TypeDef i2cTransfer;
I2C_TransferReturn_TypeDef transactionResult = i2cTransferInProgress;
@@ -458,21 +456,18 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
break;
}
- // dereference the write and read SpanByte from the arguments
+ // dereference the write and read Span from the arguments
writeSpanByte = stack.Arg1().Dereference();
if (writeSpanByte != nullptr)
{
// get buffer
- writeBuffer = writeSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ writeBuffer = writeSpanByte[Span::FIELD___array].DereferenceArray();
if (writeBuffer != nullptr)
{
- // Get the write offset, only the elements defined by the span must be written, not the whole array
- writeOffset = writeSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
-
// use the span length as write size, only the elements defined by the span must be written
- palI2c->WriteSize = writeSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
+ palI2c->WriteSize = writeSpanByte[Span::FIELD___length].NumericByRef().s4;
// pin the buffer so DMA can find it where its supposed to be
writeBuffer->Pin();
@@ -490,15 +485,12 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
if (readSpanByte != nullptr)
{
// get buffer
- readBuffer = readSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ readBuffer = readSpanByte[Span::FIELD___array].DereferenceArray();
if (readBuffer != nullptr)
{
- // Get the read offset, only the elements defined by the span must be read, not the whole array
- readOffset = readSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
-
// use the span length as read size, only the elements defined by the span must be read
- palI2c->ReadSize = readSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
+ palI2c->ReadSize = readSpanByte[Span::FIELD___length].NumericByRef().s4;
// pin the buffer so DMA can find it where its supposed to be
readBuffer->Pin();
@@ -538,13 +530,13 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
if (writeBuffer != nullptr)
{
// grab the pointer to the array by starting and the offset specified in the span
- palI2c->WriteBuffer = (uint8_t *)writeBuffer->GetElement(writeOffset);
+ palI2c->WriteBuffer = (uint8_t *)writeBuffer->GetFirstElement();
}
if (readBuffer != nullptr)
{
// grab the pointer to the array by starting and the offset specified in the span
- palI2c->ReadBuffer = (uint8_t *)readBuffer->GetElement(readOffset);
+ palI2c->ReadBuffer = (uint8_t *)readBuffer->GetFirstElement();
}
}
diff --git a/targets/AzureRTOS/SiliconLabs/_nanoCLR/nanoFramework.System.IO.Hashing/nf_sys_io_hashing_System_IO_Hashing_Crc32.cpp b/targets/AzureRTOS/SiliconLabs/_nanoCLR/nanoFramework.System.IO.Hashing/nf_sys_io_hashing_System_IO_Hashing_Crc32.cpp
index 5e63e04977..7853204544 100644
--- a/targets/AzureRTOS/SiliconLabs/_nanoCLR/nanoFramework.System.IO.Hashing/nf_sys_io_hashing_System_IO_Hashing_Crc32.cpp
+++ b/targets/AzureRTOS/SiliconLabs/_nanoCLR/nanoFramework.System.IO.Hashing/nf_sys_io_hashing_System_IO_Hashing_Crc32.cpp
@@ -10,7 +10,7 @@
#include
#include
-typedef Library_corlib_native_System_SpanByte SpanByte;
+typedef Library_corlib_native_System_Span_1 Span;
HRESULT Library_nf_sys_io_hashing_System_IO_Hashing_Crc32::ComputeHash___STATIC__U4__U4__SystemSpanByte(
CLR_RT_StackFrame &stack)
@@ -21,7 +21,6 @@ HRESULT Library_nf_sys_io_hashing_System_IO_Hashing_Crc32::ComputeHash___STATIC_
CLR_RT_HeapBlock_Array *buffer;
uint8_t *bufferData = nullptr;
int16_t bufferSize = 0;
- int16_t bufferOffset = 0;
uint32_t crc32 = 0;
uint32_t hash = 0;
@@ -33,14 +32,11 @@ HRESULT Library_nf_sys_io_hashing_System_IO_Hashing_Crc32::ComputeHash___STATIC_
crc32 = stack.Arg0().NumericByRef().u4;
// get buffer
- buffer = bufferSpanByte[SpanByte::FIELD___array].DereferenceArray();
-
- // Get the write offset
- bufferOffset = bufferSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
+ buffer = bufferSpanByte[Span::FIELD___array].DereferenceArray();
// use the span length as write size, only the elements defined by the span must be written
- bufferSize = bufferSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
- bufferData = (unsigned char *)buffer->GetElement(bufferOffset);
+ bufferSize = bufferSpanByte[Span::FIELD___length].NumericByRef().s4;
+ bufferData = (unsigned char *)buffer->GetFirstElement();
if (bufferSize == 0)
{
diff --git a/targets/ChibiOS/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp b/targets/ChibiOS/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
index c826100089..f3b8f7b8ff 100644
--- a/targets/ChibiOS/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
+++ b/targets/ChibiOS/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
@@ -7,7 +7,7 @@
typedef Library_sys_dev_i2c_native_System_Device_I2c_I2cConnectionSettings I2cConnectionSettings;
typedef Library_sys_dev_i2c_native_System_Device_I2c_I2cTransferResult I2cTransferResult;
-typedef Library_corlib_native_System_SpanByte SpanByte;
+typedef Library_corlib_native_System_Span_1 Span;
////////////////////////////////////////////
// declaration of the the I2C PAL structs //
@@ -365,8 +365,6 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
CLR_RT_HeapBlock *connectionSettings;
CLR_RT_HeapBlock_Array *writeBuffer = nullptr;
CLR_RT_HeapBlock_Array *readBuffer = nullptr;
- int readOffset = 0;
- int writeOffset = 0;
// get a pointer to the managed object instance and check that it's not nullptr
CLR_RT_HeapBlock *pThis = stack.This();
@@ -407,19 +405,16 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
break;
}
- // dereference the write and read SpanByte from the arguments
+ // dereference the write and read Span from the arguments
writeSpanByte = stack.Arg1().Dereference();
if (writeSpanByte != nullptr)
{
// get buffer
- writeBuffer = writeSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ writeBuffer = writeSpanByte[Span::FIELD___array].DereferenceArray();
if (writeBuffer != nullptr)
{
- // Get the write offset, only the elements defined by the span must be written, not the whole array
- writeOffset = writeSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
-
// use the span length as write size, only the elements defined by the span must be written
- palI2c->WriteSize = writeSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
+ palI2c->WriteSize = writeSpanByte[Span::FIELD___length].NumericByRef().s4;
// pin the buffer so DMA can find it where its supposed to be
writeBuffer->Pin();
@@ -436,14 +431,11 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
if (readSpanByte != nullptr)
{
// get buffer
- readBuffer = readSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ readBuffer = readSpanByte[Span::FIELD___array].DereferenceArray();
if (readBuffer != nullptr)
{
- // Get the read offset, only the elements defined by the span must be read, not the whole array
- readOffset = readSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
-
// use the span length as read size, only the elements defined by the span must be read
- palI2c->ReadSize = readSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
+ palI2c->ReadSize = readSpanByte[Span::FIELD___length].NumericByRef().s4;
// pin the buffer so DMA can find it where its supposed to be
readBuffer->Pin();
@@ -486,7 +478,7 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
if (writeBuffer != nullptr)
{
// grab the pointer to the array by starting and the offset specified in the span
- palI2c->WriteBuffer = (uint8_t *)writeBuffer->GetElement(writeOffset);
+ palI2c->WriteBuffer = (uint8_t *)writeBuffer->GetFirstElement();
// flush DMA buffer to ensure cache coherency
// (only required for Cortex-M7)
@@ -496,7 +488,7 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
if (readBuffer != nullptr)
{
// grab the pointer to the array by starting and the offset specified in the span
- palI2c->ReadBuffer = (uint8_t *)readBuffer->GetElement(readOffset);
+ palI2c->ReadBuffer = (uint8_t *)readBuffer->GetFirstElement();
}
// because the bus access is shared, acquire the appropriate bus
diff --git a/targets/ChibiOS/_nanoCLR/nanoFramework.System.IO.Hashing/nf_sys_io_hashing_System_IO_Hashing_Crc32.cpp b/targets/ChibiOS/_nanoCLR/nanoFramework.System.IO.Hashing/nf_sys_io_hashing_System_IO_Hashing_Crc32.cpp
index 9520fa5aa8..75b5eb6e31 100644
--- a/targets/ChibiOS/_nanoCLR/nanoFramework.System.IO.Hashing/nf_sys_io_hashing_System_IO_Hashing_Crc32.cpp
+++ b/targets/ChibiOS/_nanoCLR/nanoFramework.System.IO.Hashing/nf_sys_io_hashing_System_IO_Hashing_Crc32.cpp
@@ -7,7 +7,7 @@
#include
#include
-typedef Library_corlib_native_System_SpanByte SpanByte;
+typedef Library_corlib_native_System_Span_1 Span;
// set config to use standard CRC32
crcConfig crc32Config = {
@@ -27,7 +27,6 @@ HRESULT Library_nf_sys_io_hashing_System_IO_Hashing_Crc32::ComputeHash___STATIC_
CLR_RT_HeapBlock_Array *buffer;
uint8_t *bufferData = nullptr;
int16_t bufferSize = 0;
- int16_t bufferOffset = 0;
uint32_t crc32 = 0;
uint32_t hash = 0;
@@ -39,14 +38,11 @@ HRESULT Library_nf_sys_io_hashing_System_IO_Hashing_Crc32::ComputeHash___STATIC_
crc32 = stack.Arg0().NumericByRef().u4;
// get buffer
- buffer = bufferSpanByte[SpanByte::FIELD___array].DereferenceArray();
-
- // Get the write offset
- bufferOffset = bufferSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
+ buffer = bufferSpanByte[Span::FIELD___array].DereferenceArray();
// use the span length as write size, only the elements defined by the span must be written
- bufferSize = bufferSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
- bufferData = (unsigned char *)buffer->GetElement(bufferOffset);
+ bufferSize = bufferSpanByte[Span::FIELD___length].NumericByRef().s4;
+ bufferData = (unsigned char *)buffer->GetFirstElement();
crcAquireModule();
diff --git a/targets/ESP32/_nanoCLR/System.Device.I2c.Slave/sys_dev_i2c_slave_native_System_Device_I2c_I2cSlaveDevice.cpp b/targets/ESP32/_nanoCLR/System.Device.I2c.Slave/sys_dev_i2c_slave_native_System_Device_I2c_I2cSlaveDevice.cpp
index a25e4da369..e758206b3e 100644
--- a/targets/ESP32/_nanoCLR/System.Device.I2c.Slave/sys_dev_i2c_slave_native_System_Device_I2c_I2cSlaveDevice.cpp
+++ b/targets/ESP32/_nanoCLR/System.Device.I2c.Slave/sys_dev_i2c_slave_native_System_Device_I2c_I2cSlaveDevice.cpp
@@ -11,7 +11,7 @@
#define I2C_SLAVE_WORKER_TASK_STACK_SIZE 2048
-typedef Library_corlib_native_System_SpanByte SpanByte;
+typedef Library_corlib_native_System_Span_1 Span;
#if SOC_I2C_NUM > 0
NF_PAL_I2CSLAVE I2cSlave0_PAL;
@@ -221,7 +221,6 @@ HRESULT Library_sys_dev_i2c_slave_native_System_Device_I2c_I2cSlaveDevice::
NF_PAL_I2CSLAVE *palI2c = nullptr;
- int32_t bufferOffset = 0;
int32_t requestedCount = 0;
uint32_t readCount = 0;
uint32_t bytesTransfered = 0;
@@ -264,31 +263,25 @@ HRESULT Library_sys_dev_i2c_slave_native_System_Device_I2c_I2cSlaveDevice::
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
}
- readBuffer = readSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ readBuffer = readSpanByte[Span::FIELD___array].DereferenceArray();
if (readBuffer != nullptr)
{
// set flag to read operation
isRead = true;
- // Get the read offset, only the elements defined by the span must be read, not the whole array
- bufferOffset = readSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
-
// use the span length as read size, only the elements defined by the span must be read
- requestedCount = readSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
+ requestedCount = readSpanByte[Span::FIELD___length].NumericByRef().s4;
}
if (!isRead)
{
- writeBuffer = writeSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ writeBuffer = writeSpanByte[Span::FIELD___array].DereferenceArray();
if (writeBuffer != nullptr)
{
- // Get the write offset, only the elements defined by the span must be written, not the whole array
- bufferOffset = writeSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
-
// use the span length as write size, only the elements defined by the span must be written
- requestedCount = writeSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
+ requestedCount = writeSpanByte[Span::FIELD___length].NumericByRef().s4;
}
}
@@ -384,7 +377,7 @@ HRESULT Library_sys_dev_i2c_slave_native_System_Device_I2c_I2cSlaveDevice::
// write operation
// copy buffer content to working buffer
- memcpy(palI2c->Buffer, (uint8_t *)writeBuffer->GetElement(bufferOffset), requestedCount);
+ memcpy(palI2c->Buffer, (uint8_t *)writeBuffer->GetFirstElement(), requestedCount);
if (requestedCount < I2C_SLAVE_TX_BUF_LEN)
{
@@ -478,7 +471,7 @@ HRESULT Library_sys_dev_i2c_slave_native_System_Device_I2c_I2cSlaveDevice::
{
// copy over to the managed buffer
// grab the pointer to the array by starting and the offset specified in the span
- memcpy(readBuffer->GetElement(bufferOffset), palI2c->Buffer, bytesTransfered);
+ memcpy(readBuffer->GetFirstElement(), palI2c->Buffer, bytesTransfered);
}
// pop read count from the stack
diff --git a/targets/ESP32/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp b/targets/ESP32/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
index 76b962abc1..74d1c3a8ea 100644
--- a/targets/ESP32/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
+++ b/targets/ESP32/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
@@ -13,7 +13,7 @@
typedef Library_sys_dev_i2c_native_System_Device_I2c_I2cConnectionSettings I2cConnectionSettings;
typedef Library_sys_dev_i2c_native_System_Device_I2c_I2cTransferResult I2cTransferResult;
-typedef Library_corlib_native_System_SpanByte SpanByte;
+typedef Library_corlib_native_System_Span_1 Span;
bool SetConfig(i2c_port_t bus, CLR_RT_HeapBlock *config)
{
@@ -136,9 +136,7 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
uint8_t *writeBuffer = nullptr;
uint8_t *readBuffer = nullptr;
- int writeOffset = 0;
int writeSize = 0;
- int readOffset = 0;
int readSize = 0;
esp_err_t opResult;
uint32_t transferResult;
@@ -171,19 +169,16 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
cmd = i2c_cmd_link_create();
- // dereference the write and read SpanByte from the arguments
+ // dereference the write and read Span from the arguments
writeSpanByte = stack.Arg1().Dereference();
if (writeSpanByte != nullptr)
{
- writeData = writeSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ writeData = writeSpanByte[Span::FIELD___array].DereferenceArray();
if (writeData != nullptr)
{
- // Get the write offset, only the elements defined by the span must be written, not the whole array
- writeOffset = writeSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
-
// use the span length as write size, only the elements defined by the span must be written
- writeSize = writeSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
+ writeSize = writeSpanByte[Span::FIELD___length].NumericByRef().s4;
if (writeSize > 0)
{
@@ -196,7 +191,7 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
}
// copy buffer content
- memcpy(writeBuffer, (uint8_t *)writeData->GetElement(writeOffset), writeSize);
+ memcpy(writeBuffer, (uint8_t *)writeData->GetFirstElement(), writeSize);
// setup write transaction
i2c_master_start(cmd);
@@ -214,15 +209,12 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
readSpanByte = stack.Arg2().Dereference();
if (readSpanByte != 0)
{
- readData = readSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ readData = readSpanByte[Span::FIELD___array].DereferenceArray();
if (readData != nullptr)
{
- // Get the read offset, only the elements defined by the span must be read, not the whole array
- readOffset = readSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
-
// use the span length as read size, only the elements defined by the span must be read
- readSize = readSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
+ readSize = readSpanByte[Span::FIELD___length].NumericByRef().s4;
if (readSize > 0)
{
@@ -295,7 +287,7 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
if (readSize > 0)
{
// grab the pointer to the array by starting and the offset specified in the span
- memcpy(readData->GetElement(readOffset), readBuffer, readSize);
+ memcpy(readData->GetFirstElement(), readBuffer, readSize);
}
result[I2cTransferResult::FIELD___status].SetInteger((CLR_UINT32)I2cTransferStatus_FullTransfer);
diff --git a/targets/ESP32/_nanoCLR/System.Device.I2s/sys_dev_i2s_native_System_Device_I2s_I2sDevice.cpp b/targets/ESP32/_nanoCLR/System.Device.I2s/sys_dev_i2s_native_System_Device_I2s_I2sDevice.cpp
index 6ae31b52f8..cf8da95c5a 100644
--- a/targets/ESP32/_nanoCLR/System.Device.I2s/sys_dev_i2s_native_System_Device_I2s_I2sDevice.cpp
+++ b/targets/ESP32/_nanoCLR/System.Device.I2s/sys_dev_i2s_native_System_Device_I2s_I2sDevice.cpp
@@ -21,7 +21,7 @@
#define I2S_RX_FRAME_SIZE_IN_BYTES (8)
typedef Library_sys_dev_i2s_native_System_Device_I2s_I2sConnectionSettings I2sConnectionSettings;
-typedef Library_corlib_native_System_SpanByte SpanByte;
+typedef Library_corlib_native_System_Span_1 Span;
static char Esp_I2S_Initialised_Flag[I2S_NUM_MAX] = {
0,
@@ -319,7 +319,7 @@ HRESULT SetI2sConfig(i2s_port_t bus, CLR_RT_HeapBlock *config)
#endif
}
-#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
+#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
// apply low-level workaround for bug in some ESP-IDF versions that swap
// the left and right channels
// https://github.com/espressif/esp-idf/issues/6625
@@ -364,7 +364,6 @@ HRESULT Library_sys_dev_i2s_native_System_Device_I2s_I2sDevice::Read___VOID__Sys
CLR_RT_HeapBlock_Array *readBuffer = nullptr;
uint8_t *readData = nullptr;
int readSize = 0;
- int readOffset = 0;
uint8_t transform_buffer[SIZEOF_TRANSFORM_BUFFER_IN_BYTES];
uint32_t a_index = 0;
@@ -392,23 +391,20 @@ HRESULT Library_sys_dev_i2s_native_System_Device_I2s_I2sDevice::Read___VOID__Sys
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
}
- // dereference the SpanByte from the arguments
+ // dereference the Span from the arguments
readSpanByte = stack.Arg1().Dereference();
if (readSpanByte != nullptr)
{
- readBuffer = readSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ readBuffer = readSpanByte[Span::FIELD___array].DereferenceArray();
if (readBuffer != nullptr)
{
- // Get the read offset, only the elements defined by the span must be read, not the whole array
- readOffset = readSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
-
// use the span length as read size, only the elements defined by the span must be read
- readSize = readSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
+ readSize = readSpanByte[Span::FIELD___length].NumericByRef().s4;
if (readSize > 0)
{
- readData = (uint8_t *)readBuffer->GetElement(readOffset);
+ readData = (uint8_t *)readBuffer->GetFirstElement();
uint32_t num_bytes_needed_from_dma =
readSize * (I2S_RX_FRAME_SIZE_IN_BYTES / appbuf_sample_size_in_bytes);
@@ -485,7 +481,6 @@ HRESULT Library_sys_dev_i2s_native_System_Device_I2s_I2sDevice::Write___VOID__Sy
CLR_RT_HeapBlock_Array *writeBuffer = nullptr;
uint8_t *writeData = nullptr;
int writeSize = 0;
- int writeOffset = 0;
size_t bytesWritten;
esp_err_t opResult;
@@ -508,24 +503,21 @@ HRESULT Library_sys_dev_i2s_native_System_Device_I2s_I2sDevice::Write___VOID__Sy
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
}
- // dereference the write and read SpanByte from the arguments
+ // dereference the write and read Span from the arguments
writeSpanByte = stack.Arg1().Dereference();
if (writeSpanByte != nullptr)
{
- writeBuffer = writeSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ writeBuffer = writeSpanByte[Span::FIELD___array].DereferenceArray();
if (writeBuffer != nullptr)
{
- // Get the write offset, only the elements defined by the span must be written, not the whole array
- writeOffset = writeSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
-
// use the span length as write size, only the elements defined by the span must be written
- writeSize = writeSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
+ writeSize = writeSpanByte[Span::FIELD___length].NumericByRef().s4;
if (writeSize > 0)
{
CLR_RT_ProtectFromGC gcWriteBuffer(*writeBuffer);
- writeData = (unsigned char *)writeBuffer->GetElement(writeOffset);
+ writeData = (unsigned char *)writeBuffer->GetFirstElement();
if (bitsPerSample == I2S_BITS_PER_SAMPLE_32BIT)
{
diff --git a/targets/ESP32/_nanoCLR/nanoFramework.System.IO.Hashing/nf_sys_io_hashing_System_IO_Hashing_Crc32.cpp b/targets/ESP32/_nanoCLR/nanoFramework.System.IO.Hashing/nf_sys_io_hashing_System_IO_Hashing_Crc32.cpp
index 3dd2b12652..6871a99569 100644
--- a/targets/ESP32/_nanoCLR/nanoFramework.System.IO.Hashing/nf_sys_io_hashing_System_IO_Hashing_Crc32.cpp
+++ b/targets/ESP32/_nanoCLR/nanoFramework.System.IO.Hashing/nf_sys_io_hashing_System_IO_Hashing_Crc32.cpp
@@ -6,7 +6,7 @@
#include
#include
-typedef Library_corlib_native_System_SpanByte SpanByte;
+typedef Library_corlib_native_System_Span_1 Span;
HRESULT Library_nf_sys_io_hashing_System_IO_Hashing_Crc32::ComputeHash___STATIC__U4__U4__SystemSpanByte(
CLR_RT_StackFrame &stack)
@@ -17,7 +17,6 @@ HRESULT Library_nf_sys_io_hashing_System_IO_Hashing_Crc32::ComputeHash___STATIC_
CLR_RT_HeapBlock_Array *buffer;
uint8_t *bufferData = nullptr;
int16_t bufferSize = 0;
- int16_t bufferOffset = 0;
uint32_t crc32 = 0;
uint32_t hash = 0;
@@ -29,14 +28,11 @@ HRESULT Library_nf_sys_io_hashing_System_IO_Hashing_Crc32::ComputeHash___STATIC_
crc32 = stack.Arg0().NumericByRef().u4;
// get buffer
- buffer = bufferSpanByte[SpanByte::FIELD___array].DereferenceArray();
-
- // Get the write offset
- bufferOffset = bufferSpanByte[SpanByte::FIELD___start].NumericByRef().s4;
+ buffer = bufferSpanByte[Span::FIELD___array].DereferenceArray();
// use the span length as write size, only the elements defined by the span must be written
- bufferSize = bufferSpanByte[SpanByte::FIELD___length].NumericByRef().s4;
- bufferData = (unsigned char *)buffer->GetElement(bufferOffset);
+ bufferSize = bufferSpanByte[Span::FIELD___length].NumericByRef().s4;
+ bufferData = (unsigned char *)buffer->GetFirstElement();
#ifdef ESP_ROM_HAS_CRC_LE
diff --git a/targets/FreeRTOS/NXP/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp b/targets/FreeRTOS/NXP/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
index 8d2bf36618..b2c8ea4259 100644
--- a/targets/FreeRTOS/NXP/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
+++ b/targets/FreeRTOS/NXP/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
@@ -32,7 +32,7 @@ static LPI2C_Type *i2cBaseAddress[] = LPI2C_BASE_PTRS;
typedef Library_sys_dev_i2c_native_System_Device_I2c_I2cConnectionSettings I2cConnectionSettings;
typedef Library_sys_dev_i2c_native_System_Device_I2c_I2cTransferResult I2cTransferResult;
-typedef Library_corlib_native_System_SpanByte SpanByte;
+typedef Library_corlib_native_System_Span_1 Span;
i2c_structure_t *I2C_ChoosePeripheralStructure(uint8_t busIndex)
{
@@ -309,12 +309,12 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
I2C_ClearBuffers(pI2Cx);
- // dereference the write and read SpanByte from the arguments
+ // dereference the write and read Span from the arguments
writeSpanByte = stack.Arg1().Dereference();
if (writeSpanByte != nullptr)
{
// get buffer
- writeBuffer = writeSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ writeBuffer = writeSpanByte[Span::FIELD___array].DereferenceArray();
if (writeBuffer != nullptr)
{
pI2Cx->txBuffer = writeBuffer->GetFirstElement();
@@ -332,7 +332,7 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
if (readSpanByte != nullptr)
{
// get buffer
- readBuffer = readSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ readBuffer = readSpanByte[Span::FIELD___array].DereferenceArray();
if (readBuffer != nullptr)
{
pI2Cx->rxBuffer = readBuffer->GetFirstElement();
diff --git a/targets/TI_SimpleLink/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp b/targets/TI_SimpleLink/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
index f86afb251e..9f4827409d 100644
--- a/targets/TI_SimpleLink/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
+++ b/targets/TI_SimpleLink/_nanoCLR/System.Device.I2c/sys_dev_i2c_native_System_Device_I2c_I2cDevice.cpp
@@ -7,7 +7,7 @@
typedef Library_sys_dev_i2c_native_System_Device_I2c_I2cConnectionSettings I2cConnectionSettings;
typedef Library_sys_dev_i2c_native_System_Device_I2c_I2cTransferResult I2cTransferResult;
-typedef Library_corlib_native_System_SpanByte SpanByte;
+typedef Library_corlib_native_System_Span_1 Span;
/////////////////////////////////////////////////////
// I2C PAL structs declared in sys_dev_i2c_native.h //
@@ -178,12 +178,12 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
break;
}
- // dereference the write and read SpanByte from the arguments
+ // dereference the write and read Span from the arguments
writeSpanByte = stack.Arg1().Dereference();
if (writeSpanByte != nullptr)
{
// get buffer
- writeBuffer = writeSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ writeBuffer = writeSpanByte[Span::FIELD___array].DereferenceArray();
if (writeBuffer != nullptr)
{
// get the size of the buffer by reading the number of elements in the CLR_RT_HeapBlock_Array
@@ -201,7 +201,7 @@ HRESULT Library_sys_dev_i2c_native_System_Device_I2c_I2cDevice::
if (readSpanByte != nullptr)
{
// get buffer
- readBuffer = readSpanByte[SpanByte::FIELD___array].DereferenceArray();
+ readBuffer = readSpanByte[Span::FIELD___array].DereferenceArray();
if (readBuffer != nullptr)
{
// get the size of the buffer by reading the number of elements in the CLR_RT_HeapBlock_Array