From c1efb324560424d27ff84608b331fdbc0a8f2155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Sim=C3=B5es?= Date: Tue, 24 Jun 2025 12:33:11 +0100 Subject: [PATCH 1/4] Fix locals initialization with generic instance - Now the generic type is instanciated. Not using the TypeSpec anymore. --- src/CLR/Core/Execution.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/CLR/Core/Execution.cpp b/src/CLR/Core/Execution.cpp index 1c86247f0b..0e2170a5b9 100644 --- a/src/CLR/Core/Execution.cpp +++ b/src/CLR/Core/Execution.cpp @@ -1963,10 +1963,17 @@ HRESULT CLR_RT_ExecutionEngine::InitializeLocals( // otherwise the comparison won't be possible sig--; - if (!assembly->FindTypeSpec(sig, typeSpecIndex)) - { - 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); + + CLR_RT_SignatureParser::Element element; + NANOCLR_CHECK_HRESULT(sp.Advance(element)); + + // element.Class and element.DataType represent the T + cls = element.Class; + dt = element.DataType; + goto done; case DATATYPE_VAR: From f71ab281ea75a42bb12109a207600da8d9f1fc70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Sim=C3=B5es?= Date: Tue, 24 Jun 2025 12:44:39 +0100 Subject: [PATCH 2/4] Revert "Fix load and store field IL instructions for value types in stack (#3186)" This reverts commit 4854f6b7e4e270a1d3e5c549d61d4dfd524ca3f3. --- src/CLR/Core/Interpreter.cpp | 58 ++---------------------------------- 1 file changed, 3 insertions(+), 55 deletions(-) diff --git a/src/CLR/Core/Interpreter.cpp b/src/CLR/Core/Interpreter.cpp index c1c6873ff1..4a3f1cd371 100644 --- a/src/CLR/Core/Interpreter.cpp +++ b/src/CLR/Core/Interpreter.cpp @@ -2569,33 +2569,7 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg) CLR_RT_HeapBlock *obj = &evalPos[0]; NanoCLRDataType dt = obj->DataType(); - // If it's a byref, it must be a struct instance on the stack/heap - bool instanceIsByRef = - (obj->DataType() == DATATYPE_BYREF) || (obj->DataType() == DATATYPE_ARRAY_BYREF); - - if (instanceIsByRef) - { - // extra check for DATATYPE_DATETIME and DATATYPE_TIMESPAN (special cases) - if (obj->Dereference()->DataType() == DATATYPE_DATETIME || - obj->Dereference()->DataType() == DATATYPE_TIMESPAN) - { - NANOCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractObjectAndDataType(obj, dt)); - } - else - { - // we already have a pointer to the raw struct - dt = DATATYPE_VALUETYPE; - - obj = obj->Dereference(); - FAULT_ON_NULL(obj); - } - } - else - { - // ordinary object/array - FAULT_ON_NULL(obj); - NANOCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractObjectAndDataType(obj, dt)); - } + NANOCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractObjectAndDataType(obj, dt)); switch (dt) { @@ -2691,35 +2665,9 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg) } CLR_RT_HeapBlock *obj = &evalPos[1]; - NanoCLRDataType dt; - - // If it's a byref, it must be a struct instance on the stack/heap - bool instanceIsByRef = - (obj->DataType() == DATATYPE_BYREF) || (obj->DataType() == DATATYPE_ARRAY_BYREF); - - if (instanceIsByRef) - { - // extra check for DATATYPE_DATETIME and DATATYPE_TIMESPAN (special cases) - if (obj->Dereference()->DataType() == DATATYPE_DATETIME || - obj->Dereference()->DataType() == DATATYPE_TIMESPAN) - { - NANOCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractObjectAndDataType(obj, dt)); - } - else - { - // we already have a pointer to the raw struct - dt = DATATYPE_VALUETYPE; + NanoCLRDataType dt = obj->DataType(); - // follow the byref so obj really points at the struct - obj = obj->Dereference(); - } - } - else - { - // ordinary object/array - FAULT_ON_NULL(obj); - NANOCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractObjectAndDataType(obj, dt)); - } + NANOCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractObjectAndDataType(obj, dt)); switch (dt) { From 65125a94060a7f8f85bb617031e0b8dc3dce944b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Sim=C3=B5es?= Date: Tue, 24 Jun 2025 12:45:11 +0100 Subject: [PATCH 3/4] No need to instanciate DATATYPE_GENERICINST --- src/CLR/Core/Execution.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/CLR/Core/Execution.cpp b/src/CLR/Core/Execution.cpp index 0e2170a5b9..6664916cb4 100644 --- a/src/CLR/Core/Execution.cpp +++ b/src/CLR/Core/Execution.cpp @@ -2088,13 +2088,6 @@ HRESULT CLR_RT_ExecutionEngine::InitializeLocals( NANOCLR_CHECK_HRESULT(NewObject(*locals, inst)); } } - else if (dt == DATATYPE_GENERICINST) - { - // locals for generic instances are always OBJECT type - dt = DATATYPE_OBJECT; - locals->SetDataId(CLR_RT_HEAPBLOCK_RAW_ID(dt, CLR_RT_HeapBlock::HB_Alive, 1)); - locals->ClearData(); - } else { if (c_CLR_RT_DataTypeLookup[dt].m_flags & CLR_RT_DataTypeLookup::c_Reference) From 635d99c9ad3eb57139bd7071dbec53feb0028a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Sim=C3=B5es?= Date: Tue, 24 Jun 2025 13:08:40 +0100 Subject: [PATCH 4/4] Code style and compiler warning fixes --- src/CLR/Core/Execution.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/CLR/Core/Execution.cpp b/src/CLR/Core/Execution.cpp index 6664916cb4..f1629f98e5 100644 --- a/src/CLR/Core/Execution.cpp +++ b/src/CLR/Core/Execution.cpp @@ -1915,7 +1915,6 @@ HRESULT CLR_RT_ExecutionEngine::InitializeLocals( { NanoCLRDataType dt = DATATYPE_VOID; CLR_RT_TypeDef_Index cls; - CLR_RT_TypeSpec_Index typeSpecIndex; CLR_UINT32 levels = 0; NanoCLRDataType dtModifier = DATATYPE_VOID; @@ -1984,7 +1983,7 @@ HRESULT CLR_RT_ExecutionEngine::InitializeLocals( // parse the locals-signature to extract that T CLR_RT_SignatureParser parser; parser.Initialize_MethodLocals(assembly, methodDef); - CLR_RT_SignatureParser::Element element; + CLR_RT_SignatureParser::Element sigElement; // ensure we don’t walk past the available generic parameters const int maxParams = methodDefInstance.target->genericParamCount; @@ -1994,17 +1993,17 @@ HRESULT CLR_RT_ExecutionEngine::InitializeLocals( } // advance into the VAR entry - parser.Advance(element); + parser.Advance(sigElement); // walk forward to the Nth generic-parameter for (int i = 0; i < genericParamPosition; i++) { - parser.Advance(element); + parser.Advance(sigElement); } // element.Class and element.DataType represent the T - cls = element.Class; - dt = element.DataType; + cls = sigElement.Class; + dt = sigElement.DataType; goto done; }