Skip to content

Commit d3f31e2

Browse files
authored
More fixes with generics (#3209)
1 parent 89cfb9f commit d3f31e2

File tree

4 files changed

+126
-35
lines changed

4 files changed

+126
-35
lines changed

src/CLR/Core/CLR_RT_HeapBlock_Array.cpp

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ HRESULT CLR_RT_HeapBlock_Array::CreateInstance(
1818
CLR_RT_HeapBlock_Array *pArray;
1919
CLR_RT_TypeDef_Index cls;
2020
CLR_RT_TypeDef_Instance inst{};
21-
CLR_RT_TypeDescriptor desc{};
22-
CLR_RT_ReflectionDef_Index workingReflex = reflex;
2321

2422
reference.SetObjectReference(nullptr);
2523

@@ -28,31 +26,12 @@ HRESULT CLR_RT_HeapBlock_Array::CreateInstance(
2826

2927
if (reflex.kind != REFLECTION_TYPE)
3028
{
31-
// check for typespec
32-
if (reflex.kind == REFLECTION_TYPESPEC)
33-
{
34-
// get the type descriptor for the typespec
35-
(desc.InitializeFromTypeSpec(reflex.data.typeSpec));
36-
37-
// check that this ends up being a reflecion type
38-
if (desc.m_reflex.kind != REFLECTION_TYPE)
39-
{
40-
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
41-
}
42-
43-
// copy over to working reflex
44-
workingReflex = desc.m_reflex;
45-
workingReflex.levels++;
46-
}
47-
else
48-
{
49-
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
50-
}
29+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
5130
}
5231

53-
if (workingReflex.levels == 1)
32+
if (reflex.levels == 1)
5433
{
55-
cls = workingReflex.data.type;
34+
cls = reflex.data.type;
5635
}
5736
else
5837
{
@@ -115,17 +94,23 @@ HRESULT CLR_RT_HeapBlock_Array::CreateInstance(
11594

11695
CLR_RT_HeapBlock ref;
11796
CLR_RT_TypeDef_Instance cls{};
118-
CLR_RT_TypeSpec_Instance def{};
97+
CLR_RT_TypeSpec_Instance tsInst{};
11998

12099
memset(&ref, 0, sizeof(struct CLR_RT_HeapBlock));
121100

122101
if (cls.ResolveToken(tk, assm, caller))
123102
{
124103
NANOCLR_CHECK_HRESULT(ref.SetReflection(cls));
125104
}
126-
else if (def.ResolveToken(tk, assm))
105+
else if (tsInst.ResolveToken(tk, assm))
127106
{
128-
NANOCLR_CHECK_HRESULT(ref.SetReflection((CLR_RT_TypeSpec_Index)def));
107+
// Create a fake reflection index to pass the element type and levels.
108+
CLR_RT_ReflectionDef_Index reflex{};
109+
reflex.kind = REFLECTION_TYPE;
110+
reflex.levels = tsInst.levels;
111+
reflex.data.type = tsInst.cachedElementType;
112+
113+
NANOCLR_CHECK_HRESULT(ref.SetReflection(reflex));
129114
}
130115
else
131116
{

src/CLR/Core/Interpreter.cpp

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3307,13 +3307,61 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
33073307
{
33083308
case TBL_TypeSpec:
33093309
{
3310+
// this has to provide the closed instance of the type in the context of the caller'sc
33103311
CLR_RT_TypeSpec_Instance tsInst{};
3311-
if (tsInst.ResolveToken(arg, assm) == false)
3312+
if (tsInst.ResolveToken(arg, assm, &stack->m_call) == false)
33123313
{
33133314
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
33143315
}
33153316

3316-
evalPos[0].SetReflection((const CLR_RT_TypeSpec_Index &)tsInst.data);
3317+
// Check if this is an array type
3318+
if (tsInst.levels > 0)
3319+
{
3320+
// This is an array
3321+
3322+
// Create a fake reflection index to pass the element type and levels.
3323+
CLR_RT_ReflectionDef_Index reflex;
3324+
reflex.kind = REFLECTION_TYPE;
3325+
reflex.levels = tsInst.levels;
3326+
3327+
// prefer generic type
3328+
if (NANOCLR_INDEX_IS_VALID(tsInst.genericTypeDef) &&
3329+
NANOCLR_INDEX_IS_INVALID(tsInst.cachedElementType))
3330+
{
3331+
reflex.data.type = tsInst.genericTypeDef;
3332+
}
3333+
else if (NANOCLR_INDEX_IS_VALID(tsInst.cachedElementType))
3334+
{
3335+
reflex.data.type = tsInst.cachedElementType;
3336+
}
3337+
else
3338+
{
3339+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
3340+
}
3341+
3342+
evalPos[0].SetReflection(reflex);
3343+
}
3344+
else
3345+
{
3346+
// prefer generic type
3347+
if (NANOCLR_INDEX_IS_VALID(tsInst.genericTypeDef) &&
3348+
NANOCLR_INDEX_IS_INVALID(tsInst.cachedElementType))
3349+
{
3350+
evalPos[0].SetReflection((const CLR_RT_TypeSpec_Index &)tsInst.data);
3351+
}
3352+
else if (NANOCLR_INDEX_IS_VALID(tsInst.cachedElementType))
3353+
{
3354+
// set reflection with TypeDef instance
3355+
CLR_RT_TypeDef_Instance cls{};
3356+
cls.InitializeFromIndex(tsInst.cachedElementType);
3357+
3358+
evalPos[0].SetReflection(cls);
3359+
}
3360+
else
3361+
{
3362+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
3363+
}
3364+
}
33173365
}
33183366
break;
33193367

src/CLR/Core/TypeSystem.cpp

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,9 @@ HRESULT CLR_RT_SignatureParser::Advance(Element &res)
615615

616616
// need to update the parser counter too
617617
ParamCount = GenParamCount;
618+
619+
// reset the generic instance flag
620+
IsGenericInst = false;
618621
}
619622

620623
NANOCLR_SET_AND_LEAVE(S_OK);
@@ -709,7 +712,14 @@ bool CLR_RT_TypeSpec_Instance::InitializeFromIndex(const CLR_RT_TypeSpec_Index &
709712
CLR_RT_SignatureParser::Element element;
710713

711714
// if this is a generic, advance another one
712-
parser.Advance(element);
715+
if (FAILED(parser.Advance(element)))
716+
{
717+
ClearInstance();
718+
719+
return false;
720+
}
721+
722+
levels = element.Levels;
713723

714724
if (element.DataType == DATATYPE_GENERICINST)
715725
{
@@ -722,9 +732,7 @@ bool CLR_RT_TypeSpec_Instance::InitializeFromIndex(const CLR_RT_TypeSpec_Index &
722732
return true;
723733
}
724734

725-
data = 0;
726-
assembly = nullptr;
727-
target = nullptr;
735+
ClearInstance();
728736

729737
return false;
730738
}
@@ -736,9 +744,15 @@ void CLR_RT_TypeSpec_Instance::ClearInstance()
736744

737745
assembly = nullptr;
738746
target = nullptr;
747+
levels = 0;
748+
genericTypeDef.Clear();
749+
data = 0;
739750
}
740751

741-
bool CLR_RT_TypeSpec_Instance::ResolveToken(CLR_UINT32 token, CLR_RT_Assembly *assm)
752+
bool CLR_RT_TypeSpec_Instance::ResolveToken(
753+
CLR_UINT32 token,
754+
CLR_RT_Assembly *assm,
755+
const CLR_RT_MethodDef_Instance *caller)
742756
{
743757
NATIVE_PROFILE_CLR_CORE();
744758
if (assm && CLR_TypeFromTk(token) == TBL_TypeSpec)
@@ -758,13 +772,53 @@ bool CLR_RT_TypeSpec_Instance::ResolveToken(CLR_UINT32 token, CLR_RT_Assembly *a
758772
// if this is a generic, advance another one
759773
parser.Advance(element);
760774

775+
levels = element.Levels;
776+
761777
if (element.DataType == DATATYPE_GENERICINST)
762778
{
763779
// this is a generic instance, so we need to advance one more time
764780
parser.Advance(element);
765781

766782
genericTypeDef = element.Class;
767783
}
784+
else if (element.DataType == DATATYPE_VAR)
785+
{
786+
// this is type‐generic slot (!T), resolve against the caller's closed generic
787+
788+
int pos = element.GenericParamPosition;
789+
790+
// Use the *caller's* bound genericType (Stack<Int32>, etc.)
791+
if (caller == nullptr || caller->genericType == nullptr)
792+
{
793+
ClearInstance();
794+
795+
return false;
796+
}
797+
798+
auto &tsi = *caller->genericType;
799+
CLR_UINT32 closedTsRow = tsi.TypeSpec();
800+
801+
Set(caller->genericType->Assembly(), closedTsRow);
802+
assembly = g_CLR_RT_TypeSystem.m_assemblies[caller->genericType->Assembly() - 1];
803+
804+
target = assm->GetTypeSpec(closedTsRow);
805+
806+
NanoCLRDataType realDataType;
807+
808+
g_CLR_RT_TypeSystem.m_assemblies[caller->genericType->Assembly() - 1]
809+
->FindGenericParamAtTypeSpec(closedTsRow, (CLR_UINT32)pos, cachedElementType, realDataType);
810+
}
811+
else if (element.DataType == DATATYPE_MVAR)
812+
{
813+
ASSERT(false);
814+
}
815+
else
816+
{
817+
cachedElementType = element.Class;
818+
819+
genericTypeDef.Clear();
820+
}
821+
768822
return true;
769823
}
770824

@@ -981,6 +1035,7 @@ bool CLR_RT_TypeDef_Instance::ResolveToken(
9811035
const CLR_RT_MethodDef_Instance *caller)
9821036
{
9831037
NATIVE_PROFILE_CLR_CORE();
1038+
9841039
if (assm)
9851040
{
9861041
CLR_UINT32 index = CLR_DataFromTk(tk);

src/CLR/Include/nanoCLR_Runtime.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2087,13 +2087,16 @@ struct CLR_RT_TypeSpec_Instance : public CLR_RT_TypeSpec_Index
20872087
const CLR_RECORD_TYPESPEC *target;
20882088

20892089
CLR_RT_TypeDef_Index genericTypeDef;
2090+
CLR_UINT32 levels;
2091+
2092+
CLR_RT_TypeDef_Index cachedElementType;
20902093

20912094
//--//
20922095

20932096
bool InitializeFromIndex(const CLR_RT_TypeSpec_Index &index);
20942097
void ClearInstance();
20952098

2096-
bool ResolveToken(CLR_UINT32 tk, CLR_RT_Assembly *assm);
2099+
bool ResolveToken(CLR_UINT32 tk, CLR_RT_Assembly *assm, const CLR_RT_MethodDef_Instance *caller = nullptr);
20972100
};
20982101

20992102
//--//

0 commit comments

Comments
 (0)