Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 12 additions & 27 deletions src/CLR/Core/CLR_RT_HeapBlock_Array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ HRESULT CLR_RT_HeapBlock_Array::CreateInstance(
CLR_RT_HeapBlock_Array *pArray;
CLR_RT_TypeDef_Index cls;
CLR_RT_TypeDef_Instance inst{};
CLR_RT_TypeDescriptor desc{};
CLR_RT_ReflectionDef_Index workingReflex = reflex;

reference.SetObjectReference(nullptr);

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

if (reflex.kind != REFLECTION_TYPE)
{
// check for typespec
if (reflex.kind == REFLECTION_TYPESPEC)
{
// get the type descriptor for the typespec
(desc.InitializeFromTypeSpec(reflex.data.typeSpec));

// check that this ends up being a reflecion type
if (desc.m_reflex.kind != REFLECTION_TYPE)
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}

// copy over to working reflex
workingReflex = desc.m_reflex;
workingReflex.levels++;
}
else
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}

if (workingReflex.levels == 1)
if (reflex.levels == 1)
{
cls = workingReflex.data.type;
cls = reflex.data.type;
}
else
{
Expand Down Expand Up @@ -115,17 +94,23 @@ HRESULT CLR_RT_HeapBlock_Array::CreateInstance(

CLR_RT_HeapBlock ref;
CLR_RT_TypeDef_Instance cls{};
CLR_RT_TypeSpec_Instance def{};
CLR_RT_TypeSpec_Instance tsInst{};

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

if (cls.ResolveToken(tk, assm, caller))
{
NANOCLR_CHECK_HRESULT(ref.SetReflection(cls));
}
else if (def.ResolveToken(tk, assm))
else if (tsInst.ResolveToken(tk, assm))
{
NANOCLR_CHECK_HRESULT(ref.SetReflection((CLR_RT_TypeSpec_Index)def));
// Create a fake reflection index to pass the element type and levels.
CLR_RT_ReflectionDef_Index reflex{};
reflex.kind = REFLECTION_TYPE;
reflex.levels = tsInst.levels;
reflex.data.type = tsInst.cachedElementType;

NANOCLR_CHECK_HRESULT(ref.SetReflection(reflex));
}
else
{
Expand Down
52 changes: 50 additions & 2 deletions src/CLR/Core/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3307,13 +3307,61 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
{
case TBL_TypeSpec:
{
// this has to provide the closed instance of the type in the context of the caller'sc
CLR_RT_TypeSpec_Instance tsInst{};
if (tsInst.ResolveToken(arg, assm) == false)
if (tsInst.ResolveToken(arg, assm, &stack->m_call) == false)
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}

evalPos[0].SetReflection((const CLR_RT_TypeSpec_Index &)tsInst.data);
// Check if this is an array type
if (tsInst.levels > 0)
{
// This is an array

// Create a fake reflection index to pass the element type and levels.
CLR_RT_ReflectionDef_Index reflex;
reflex.kind = REFLECTION_TYPE;
reflex.levels = tsInst.levels;

// prefer generic type
if (NANOCLR_INDEX_IS_VALID(tsInst.genericTypeDef) &&
NANOCLR_INDEX_IS_INVALID(tsInst.cachedElementType))
{
reflex.data.type = tsInst.genericTypeDef;
}
else if (NANOCLR_INDEX_IS_VALID(tsInst.cachedElementType))
{
reflex.data.type = tsInst.cachedElementType;
}
else
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}

evalPos[0].SetReflection(reflex);
}
else
{
// prefer generic type
if (NANOCLR_INDEX_IS_VALID(tsInst.genericTypeDef) &&
NANOCLR_INDEX_IS_INVALID(tsInst.cachedElementType))
{
evalPos[0].SetReflection((const CLR_RT_TypeSpec_Index &)tsInst.data);
}
else if (NANOCLR_INDEX_IS_VALID(tsInst.cachedElementType))
{
// set reflection with TypeDef instance
CLR_RT_TypeDef_Instance cls{};
cls.InitializeFromIndex(tsInst.cachedElementType);

evalPos[0].SetReflection(cls);
}
else
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
}
}
break;

Expand Down
65 changes: 60 additions & 5 deletions src/CLR/Core/TypeSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,9 @@ HRESULT CLR_RT_SignatureParser::Advance(Element &res)

// need to update the parser counter too
ParamCount = GenParamCount;

// reset the generic instance flag
IsGenericInst = false;
}

NANOCLR_SET_AND_LEAVE(S_OK);
Expand Down Expand Up @@ -709,7 +712,14 @@ bool CLR_RT_TypeSpec_Instance::InitializeFromIndex(const CLR_RT_TypeSpec_Index &
CLR_RT_SignatureParser::Element element;

// if this is a generic, advance another one
parser.Advance(element);
if (FAILED(parser.Advance(element)))
{
ClearInstance();

return false;
}

levels = element.Levels;

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

data = 0;
assembly = nullptr;
target = nullptr;
ClearInstance();

return false;
}
Expand All @@ -736,9 +744,15 @@ void CLR_RT_TypeSpec_Instance::ClearInstance()

assembly = nullptr;
target = nullptr;
levels = 0;
genericTypeDef.Clear();
data = 0;
}

bool CLR_RT_TypeSpec_Instance::ResolveToken(CLR_UINT32 token, CLR_RT_Assembly *assm)
bool CLR_RT_TypeSpec_Instance::ResolveToken(
CLR_UINT32 token,
CLR_RT_Assembly *assm,
const CLR_RT_MethodDef_Instance *caller)
{
NATIVE_PROFILE_CLR_CORE();
if (assm && CLR_TypeFromTk(token) == TBL_TypeSpec)
Expand All @@ -758,13 +772,53 @@ bool CLR_RT_TypeSpec_Instance::ResolveToken(CLR_UINT32 token, CLR_RT_Assembly *a
// if this is a generic, advance another one
parser.Advance(element);

levels = element.Levels;

if (element.DataType == DATATYPE_GENERICINST)
{
// this is a generic instance, so we need to advance one more time
parser.Advance(element);

genericTypeDef = element.Class;
}
else if (element.DataType == DATATYPE_VAR)
{
// this is type‐generic slot (!T), resolve against the caller's closed generic

int pos = element.GenericParamPosition;

// Use the *caller's* bound genericType (Stack<Int32>, etc.)
if (caller == nullptr || caller->genericType == nullptr)
{
ClearInstance();

return false;
}

auto &tsi = *caller->genericType;
CLR_UINT32 closedTsRow = tsi.TypeSpec();

Set(caller->genericType->Assembly(), closedTsRow);
assembly = g_CLR_RT_TypeSystem.m_assemblies[caller->genericType->Assembly() - 1];

target = assm->GetTypeSpec(closedTsRow);

NanoCLRDataType realDataType;

g_CLR_RT_TypeSystem.m_assemblies[caller->genericType->Assembly() - 1]
->FindGenericParamAtTypeSpec(closedTsRow, (CLR_UINT32)pos, cachedElementType, realDataType);
}
else if (element.DataType == DATATYPE_MVAR)
{
ASSERT(false);
}
else
{
cachedElementType = element.Class;

genericTypeDef.Clear();
}

return true;
}

Expand Down Expand Up @@ -981,6 +1035,7 @@ bool CLR_RT_TypeDef_Instance::ResolveToken(
const CLR_RT_MethodDef_Instance *caller)
{
NATIVE_PROFILE_CLR_CORE();

if (assm)
{
CLR_UINT32 index = CLR_DataFromTk(tk);
Expand Down
5 changes: 4 additions & 1 deletion src/CLR/Include/nanoCLR_Runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -2087,13 +2087,16 @@ struct CLR_RT_TypeSpec_Instance : public CLR_RT_TypeSpec_Index
const CLR_RECORD_TYPESPEC *target;

CLR_RT_TypeDef_Index genericTypeDef;
CLR_UINT32 levels;

CLR_RT_TypeDef_Index cachedElementType;

//--//

bool InitializeFromIndex(const CLR_RT_TypeSpec_Index &index);
void ClearInstance();

bool ResolveToken(CLR_UINT32 tk, CLR_RT_Assembly *assm);
bool ResolveToken(CLR_UINT32 tk, CLR_RT_Assembly *assm, const CLR_RT_MethodDef_Instance *caller = nullptr);
};

//--//
Expand Down