diff --git a/src/CLR/Core/Execution.cpp b/src/CLR/Core/Execution.cpp index 27e5b86958..b6b8fa4ec4 100644 --- a/src/CLR/Core/Execution.cpp +++ b/src/CLR/Core/Execution.cpp @@ -1971,10 +1971,26 @@ HRESULT CLR_RT_ExecutionEngine::InitializeLocals( case DATATYPE_VAR: { + // type-level generic parameter in a locals signature (e.g. 'T' inside a generic type) CLR_INT8 genericParamPosition = *sig++; - methodDefInstance.assembly - ->FindGenericParamAtTypeSpec(methodDefInstance, genericParamPosition, cls, dt); + // parse the locals-signature to extract that T + CLR_RT_SignatureParser parser; + parser.Initialize_MethodLocals(assembly, methodDef); + CLR_RT_SignatureParser::Element element; + + // advance into the VAR entry + parser.Advance(element); + + // walk forward to the Nth generic-parameter + for (int i = 0; i < genericParamPosition; i++) + { + parser.Advance(element); + } + + // element.Class and element.DataType represent the T + cls = element.Class; + dt = element.DataType; goto done; } diff --git a/src/CLR/Core/TypeSystem.cpp b/src/CLR/Core/TypeSystem.cpp index 54cde956cd..e9db8ff1e9 100644 --- a/src/CLR/Core/TypeSystem.cpp +++ b/src/CLR/Core/TypeSystem.cpp @@ -440,8 +440,6 @@ HRESULT CLR_RT_SignatureParser::Advance(Element &res) NANOCLR_HEADER(); - _ASSERTE(ParamCount > 0); - ParamCount--; res.IsByRef = false; @@ -988,13 +986,36 @@ bool CLR_RT_TypeDef_Instance::ResolveToken( case DATATYPE_VAR: { CLR_RT_TypeDef_Index typeDef; - NanoCLRDataType dataType; + CLR_RT_SignatureParser::Element genericElement; + + CLR_RT_SignatureParser varParser; + varParser.Initialize_TypeSpec(assm, ts); - caller->assembly->FindGenericParamAtTypeSpec(*caller, genericParamPosition, typeDef, dataType); + // advance once to consume the GENERICINST or VAR entry + varParser.Advance(genericElement); + + // now walk forward genericParameterPosition steps to land on the actual + // argument in the signature stream. + for (CLR_INT8 i = 0; i <= genericParamPosition; i++) + { + if (FAILED(varParser.Advance(genericElement))) + { + return false; + } + } + // genericElement.Class now holds the TypeDef_Index of the T or U, etc. + typeDef = genericElement.Class; + + // populate this instance from the resolved TypeDef data = typeDef.data; assembly = g_CLR_RT_TypeSystem.m_assemblies[typeDef.Assembly() - 1]; target = assembly->GetTypeDef(typeDef.Type()); + +#if defined(NANOCLR_INSTANCE_NAMES) + name = assembly->GetString(target->name); +#endif + return true; } break; diff --git a/src/CLR/Debugger/Debugger.cpp b/src/CLR/Debugger/Debugger.cpp index d4b902ea03..ba704063ed 100644 --- a/src/CLR/Debugger/Debugger.cpp +++ b/src/CLR/Debugger/Debugger.cpp @@ -1,4 +1,4 @@ -// +// // 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. @@ -2821,10 +2821,51 @@ bool CLR_DBG_Debugger::Debugging_Value_GetStack(WP_Message *msg) // handle generic parameters if (res.DataType == DATATYPE_VAR) { - // Generic parameter in a generic TypeDef - md.assembly->FindGenericParamAtTypeSpec(md, res.GenericParamPosition, targetClass, targetDataType); + // type‐level generic parameter in a generic TypeDef: re‐parse the signature + CLR_RT_SignatureParser parser; - // isGenericInstance = true; + // for arguments, initialize over the method signature and skip the return slot + if (cmd->m_kind == CLR_DBG_Commands::Debugging_Value_GetStack::c_Argument) + { + parser.Initialize_MethodSignature(&md); + + // skip the return value entry + iElement++; + + // if there's an implicit 'this', adjust index + if (parser.Flags & PIMAGE_CEE_CS_CALLCONV_HASTHIS) + { + if (iElement == 0) + { + // requested the 'this' argument – invalid for a primitive + return false; + } + iElement--; + } + } + else + { + // for locals or eval‐stack, initialize over the locals signature + parser.Initialize_MethodLocals(md.assembly, md.target); + } + + // advance to the requested argument/local + CLR_RT_SignatureParser::Element elem; + do + { + parser.Advance(elem); + } while (iElement-- > 0); + + // now we've landed on a DATATYPE_VAR; walk to the Nth generic‐type parameter + parser.Advance(elem); + for (int i = 0; i < res.GenericParamPosition; i++) + { + parser.Advance(elem); + } + + // this element.Class is the TypeDef_Index for 'T' + targetClass = elem.Class; + targetDataType = elem.DataType; } else if (res.DataType == DATATYPE_MVAR) { diff --git a/src/CLR/Include/nanoCLR_Runtime.h b/src/CLR/Include/nanoCLR_Runtime.h index 5134b73ed6..4de62a91bb 100644 --- a/src/CLR/Include/nanoCLR_Runtime.h +++ b/src/CLR/Include/nanoCLR_Runtime.h @@ -2154,6 +2154,11 @@ struct CLR_RT_MethodDef_Instance : public CLR_RT_MethodDef_Index const CLR_RT_TypeSpec_Index *genericType; + // the TypeSpec RID from the last resolved DATATYPE_VAR + CLR_UINT32 lastTypeSpecIndex; + // the GenericParamPosition from last resolved DATATYPE_VAR + CLR_INT8 lastGenericParamPosition; + #if defined(NANOCLR_INSTANCE_NAMES) const char *name; #endif