@@ -2028,6 +2028,40 @@ CLR_RT_HeapBlock *CLR_RT_ExecutionEngine::AccessStaticField(const CLR_RT_FieldDe
20282028 return nullptr ;
20292029}
20302030
2031+ // Helper function to resolve generic type parameters (VAR/MVAR) to their concrete types
2032+ // Used by both InitializeReference and InitializeLocals to reduce code duplication
2033+ static HRESULT ResolveGenericTypeParameter (
2034+ const CLR_RT_TypeSpec_Index &genericTypeIndex,
2035+ CLR_UINT8 paramPosition,
2036+ CLR_RT_TypeDef_Index &outClass,
2037+ NanoCLRDataType &outDataType)
2038+ {
2039+ NATIVE_PROFILE_CLR_CORE ();
2040+ NANOCLR_HEADER ();
2041+
2042+ if (!NANOCLR_INDEX_IS_VALID (genericTypeIndex))
2043+ {
2044+ NANOCLR_SET_AND_LEAVE (CLR_E_FAIL);
2045+ }
2046+
2047+ CLR_RT_TypeSpec_Instance typeSpec;
2048+ if (!typeSpec.InitializeFromIndex (genericTypeIndex))
2049+ {
2050+ NANOCLR_SET_AND_LEAVE (CLR_E_FAIL);
2051+ }
2052+
2053+ CLR_RT_SignatureParser::Element paramElement;
2054+ if (!typeSpec.GetGenericParam (paramPosition, paramElement))
2055+ {
2056+ NANOCLR_SET_AND_LEAVE (CLR_E_FAIL);
2057+ }
2058+
2059+ outClass = paramElement.Class ;
2060+ outDataType = paramElement.DataType ;
2061+
2062+ NANOCLR_NOCLEANUP ();
2063+ }
2064+
20312065HRESULT CLR_RT_ExecutionEngine::InitializeReference (
20322066 CLR_RT_HeapBlock &ref,
20332067 CLR_RT_SignatureParser &parser,
@@ -2063,8 +2097,13 @@ HRESULT CLR_RT_ExecutionEngine::InitializeReference(
20632097
20642098 if (dt == DATATYPE_VAR)
20652099 {
2066- genericInstance->assembly
2067- ->FindGenericParamAtTypeSpec (genericInstance->data , res.GenericParamPosition , realTypeDef, dt);
2100+ if (genericInstance == nullptr || !NANOCLR_INDEX_IS_VALID (*genericInstance))
2101+ {
2102+ NANOCLR_SET_AND_LEAVE (CLR_E_FAIL);
2103+ }
2104+
2105+ NANOCLR_CHECK_HRESULT (
2106+ ResolveGenericTypeParameter (*genericInstance, res.GenericParamPosition , realTypeDef, dt));
20682107
20692108 goto process_datatype;
20702109 }
@@ -2297,44 +2336,53 @@ HRESULT CLR_RT_ExecutionEngine::InitializeLocals(
22972336 // type-level generic parameter in a locals signature (e.g. 'T' inside a generic type)
22982337 CLR_INT8 genericParamPosition = *sig++;
22992338
2339+ // Resolve type-level generic parameter (VAR) using the method's enclosing type context
23002340 if (methodDefInstance.genericType && NANOCLR_INDEX_IS_VALID (*methodDefInstance.genericType ) &&
23012341 methodDefInstance.genericType ->data != CLR_EmptyToken)
23022342 {
2303- CLR_RT_TypeSpec_Instance typeSpec{};
2304- typeSpec.InitializeFromIndex (
2305- (const CLR_RT_TypeSpec_Index &)methodDefInstance.genericType ->data );
2306-
2307- typeSpec.assembly ->FindGenericParamAtTypeSpec (
2308- methodDefInstance.genericType ->data ,
2309- genericParamPosition,
2310- cls,
2311- dt);
2343+ NANOCLR_CHECK_HRESULT (
2344+ ResolveGenericTypeParameter (*methodDefInstance.genericType , genericParamPosition, cls, dt));
23122345 }
23132346 else
23142347 {
2315- assembly->FindGenericParamAtTypeSpec (
2316- methodDefInstance.genericType ->data ,
2317- genericParamPosition,
2318- cls,
2319- dt);
2348+ NANOCLR_SET_AND_LEAVE (CLR_E_FAIL);
23202349 }
23212350
23222351 goto done;
23232352 }
23242353
23252354 case DATATYPE_MVAR:
23262355 {
2356+ // Method-level generic parameter (e.g., '!!T' in a generic method like Array.Empty<T>())
23272357 CLR_UINT8 genericParamPosition = *sig++;
23282358
2329- CLR_RT_GenericParam_Index gpIndex;
2359+ // For generic methods, use the MethodSpec's signature to get the concrete type
2360+ if (NANOCLR_INDEX_IS_VALID (methodDefInstance.methodSpec ))
2361+ {
2362+ CLR_RT_MethodSpec_Instance methodSpec;
2363+ if (!methodSpec.InitializeFromIndex (methodDefInstance.methodSpec ))
2364+ {
2365+ NANOCLR_SET_AND_LEAVE (CLR_E_FAIL);
2366+ }
23302367
2331- assembly->FindGenericParamAtMethodDef (methodDefInstance, genericParamPosition, gpIndex);
2368+ // Use GetGenericArgument to get the concrete type from MethodSpec's signature
2369+ if (!methodSpec.GetGenericArgument (genericParamPosition, cls, dt))
2370+ {
2371+ NANOCLR_SET_AND_LEAVE (CLR_E_FAIL);
2372+ }
2373+ }
2374+ else
2375+ {
2376+ // Fallback: try to resolve using GenericParam table (for open generic methods)
2377+ CLR_RT_GenericParam_Index gpIndex;
2378+ assembly->FindGenericParamAtMethodDef (methodDefInstance, genericParamPosition, gpIndex);
23322379
2333- CLR_RT_GenericParam_CrossReference gp =
2334- assembly->crossReferenceGenericParam [gpIndex.GenericParam ()];
2380+ CLR_RT_GenericParam_CrossReference gp =
2381+ assembly->crossReferenceGenericParam [gpIndex.GenericParam ()];
23352382
2336- cls = gp.classTypeDef ;
2337- dt = gp.dataType ;
2383+ cls = gp.classTypeDef ;
2384+ dt = gp.dataType ;
2385+ }
23382386
23392387 goto done;
23402388 }
@@ -3538,37 +3586,20 @@ bool CLR_RT_ExecutionEngine::IsInstanceOf(
35383586 CLR_RT_HeapBlock &obj,
35393587 CLR_RT_Assembly *assm,
35403588 CLR_UINT32 token,
3541- bool isInstInstruction)
3589+ bool isInstInstruction,
3590+ const CLR_RT_MethodDef_Instance *caller)
35423591{
35433592 NATIVE_PROFILE_CLR_CORE ();
3593+
35443594 CLR_RT_TypeDescriptor desc{};
35453595 CLR_RT_TypeDescriptor descTarget{};
3546- CLR_RT_TypeDef_Instance clsTarget{};
3547- CLR_RT_TypeSpec_Instance defTarget{};
35483596
35493597 if (FAILED (desc.InitializeFromObject (obj)))
35503598 return false ;
35513599
3552- if (clsTarget.ResolveToken (token, assm))
3553- {
3554- //
3555- // Shortcut for identity.
3556- //
3557- if (desc.m_handlerCls .data == clsTarget.data )
3558- return true ;
3559-
3560- if (FAILED (descTarget.InitializeFromType (clsTarget)))
3561- return false ;
3562- }
3563- else if (defTarget.ResolveToken (token, assm))
3564- {
3565- if (FAILED (descTarget.InitializeFromTypeSpec (defTarget)))
3566- return false ;
3567- }
3568- else
3569- {
3600+ // Use InitializeFromSignatureToken to properly resolve VAR/MVAR tokens
3601+ if (FAILED (descTarget.InitializeFromSignatureToken (assm, token, caller)))
35703602 return false ;
3571- }
35723603
35733604 return IsInstanceOf (desc, descTarget, isInstInstruction);
35743605}
@@ -3609,7 +3640,8 @@ HRESULT CLR_RT_ExecutionEngine::CastToType(
36093640 CLR_RT_HeapBlock &ref,
36103641 CLR_UINT32 tk,
36113642 CLR_RT_Assembly *assm,
3612- bool isInstInstruction)
3643+ bool isInstInstruction,
3644+ const CLR_RT_MethodDef_Instance *caller)
36133645{
36143646 NATIVE_PROFILE_CLR_CORE ();
36153647 NANOCLR_HEADER ();
@@ -3618,7 +3650,7 @@ HRESULT CLR_RT_ExecutionEngine::CastToType(
36183650 {
36193651 ;
36203652 }
3621- else if (g_CLR_RT_ExecutionEngine.IsInstanceOf (ref, assm, tk, isInstInstruction) == true )
3653+ else if (g_CLR_RT_ExecutionEngine.IsInstanceOf (ref, assm, tk, isInstInstruction, caller ) == true )
36223654 {
36233655 ;
36243656 }
0 commit comments