Skip to content

Commit 89ae532

Browse files
authored
Work to add new features and fixes in type system and execution engine related with generics (#3240)
1 parent 6393d3d commit 89ae532

File tree

13 files changed

+1615
-338
lines changed

13 files changed

+1615
-338
lines changed

src/CLR/Core/CLR_RT_HeapBlock_Delegate.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ HRESULT CLR_RT_HeapBlock_Delegate::CreateInstance(
5757

5858
dlg->m_object.SetObjectReference(nullptr);
5959
dlg->m_genericTypeSpec.Clear();
60+
dlg->m_genericMethodSpec.Clear();
6061

6162
#if defined(NANOCLR_APPDOMAINS)
6263
dlg->m_appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain();

src/CLR/Core/CLR_RT_StackFrame.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,15 +118,18 @@ HRESULT CLR_RT_StackFrame::Push(CLR_RT_Thread *th, const CLR_RT_MethodDef_Instan
118118
// void* m_customPointer;
119119
// };
120120
//
121+
// Initialize generic type context storage to invalid
122+
stack->m_genericTypeSpecStorage.Clear();
123+
//
121124
#ifndef NANOCLR_NO_IL_INLINE
122125
stack->m_inlineFrame = nullptr;
123126
#endif
124127
#if defined(NANOCLR_PROFILE_NEW_CALLS)
125128
stack->m_callchain.Enter(stack); // CLR_PROF_CounterCallChain m_callchain;
126129
#endif
127-
//
128-
// CLR_RT_HeapBlock m_extension[1];
129-
//
130+
//
131+
// CLR_RT_HeapBlock m_extension[1];
132+
//
130133
#if defined(ENABLE_NATIVE_PROFILER)
131134
stack->m_fNativeProfiled = stack->m_owningThread->m_fNativeProfiled;
132135
#endif

src/CLR/Core/Execution.cpp

Lines changed: 78 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
20312065
HRESULT 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

Comments
 (0)