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