Skip to content

Commit 51a2269

Browse files
committed
Implement ctor from pointer for Span and ReadOnlySpan
- Update mscorlib declaration.
1 parent c630b82 commit 51a2269

File tree

4 files changed

+306
-1
lines changed

4 files changed

+306
-1
lines changed

src/CLR/CorLib/corlib_native.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,10 @@ static const CLR_RT_MethodHandler method_lookup[] =
696696
Library_corlib_native_System_Random::_ctor___VOID,
697697
Library_corlib_native_System_Random::_ctor___VOID__I4,
698698
nullptr,
699+
Library_corlib_native_System_ReadOnlySpan_1::_ctor___VOID__VOIDptr__I4,
700+
nullptr,
701+
nullptr,
702+
nullptr,
699703
nullptr,
700704
nullptr,
701705
nullptr,
@@ -711,6 +715,14 @@ static const CLR_RT_MethodHandler method_lookup[] =
711715
nullptr,
712716
nullptr,
713717
nullptr,
718+
nullptr,
719+
nullptr,
720+
nullptr,
721+
nullptr,
722+
nullptr,
723+
nullptr,
724+
nullptr,
725+
nullptr,
714726
Library_corlib_native_System_Reflection_ConstructorInfo::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN,
715727
Library_corlib_native_System_Reflection_ConstructorInfo::Invoke___OBJECT__SZARRAY_OBJECT,
716728
nullptr,
@@ -798,6 +810,7 @@ static const CLR_RT_MethodHandler method_lookup[] =
798810
nullptr,
799811
nullptr,
800812
nullptr,
813+
Library_corlib_native_System_Span_1::_ctor___VOID__VOIDptr__I4,
801814
nullptr,
802815
nullptr,
803816
nullptr,
@@ -827,6 +840,10 @@ static const CLR_RT_MethodHandler method_lookup[] =
827840
nullptr,
828841
nullptr,
829842
nullptr,
843+
nullptr,
844+
nullptr,
845+
nullptr,
846+
nullptr,
830847
Library_corlib_native_System_Threading_AutoResetEvent::_ctor___VOID__BOOLEAN,
831848
Library_corlib_native_System_Threading_AutoResetEvent::Reset___BOOLEAN,
832849
Library_corlib_native_System_Threading_AutoResetEvent::Set___BOOLEAN,
@@ -1596,7 +1613,7 @@ const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib =
15961613

15971614
#if (NANOCLR_REFLECTION == TRUE)
15981615

1599-
0x3C34952A,
1616+
0xCECAB752,
16001617

16011618
#elif (NANOCLR_REFLECTION == FALSE)
16021619

src/CLR/CorLib/corlib_native.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,7 @@ struct Library_corlib_native_System_ReadOnlySpan_1
783783
static const int FIELD___array = 1;
784784
static const int FIELD___length = 2;
785785

786+
NANOCLR_NATIVE_DECLARE(_ctor___VOID__VOIDptr__I4);
786787
NANOCLR_NATIVE_DECLARE(NativeReadOnlySpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4);
787788

788789
//--//
@@ -962,6 +963,7 @@ struct Library_corlib_native_System_Span_1
962963
static const int FIELD___array = 1;
963964
static const int FIELD___length = 2;
964965

966+
NANOCLR_NATIVE_DECLARE(_ctor___VOID__VOIDptr__I4);
965967
NANOCLR_NATIVE_DECLARE(CopyTo___VOID__SystemSpan_1);
966968
NANOCLR_NATIVE_DECLARE(NativeSpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4);
967969

src/CLR/CorLib/corlib_native_System_ReadOnlySpan_1.cpp

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,149 @@
66

77
#include "CorLib.h"
88

9+
typedef Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers RuntimeHelpers;
10+
11+
HRESULT Library_corlib_native_System_ReadOnlySpan_1::_ctor___VOID__VOIDptr__I4(CLR_RT_StackFrame &stack)
12+
{
13+
NANOCLR_HEADER();
14+
15+
int32_t length;
16+
bool isRefContainsRefs = false;
17+
18+
CLR_RT_HeapBlock_Array *sourceArray;
19+
20+
CLR_RT_HeapBlock *thisSpan = stack.This();
21+
22+
// grab caller to get the generic type
23+
CLR_RT_MethodDef_Instance &caller = stack.MethodCall();
24+
25+
if (caller.genericType == nullptr || !NANOCLR_INDEX_IS_VALID(*caller.genericType))
26+
{
27+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
28+
}
29+
30+
CLR_RT_TypeSpec_Instance typeSpec;
31+
if (!typeSpec.InitializeFromIndex(*caller.genericType))
32+
{
33+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
34+
}
35+
36+
CLR_RT_SignatureParser parser;
37+
parser.Initialize_TypeSpec(typeSpec);
38+
39+
CLR_RT_SignatureParser::Element element;
40+
41+
if (FAILED(parser.Advance(element)))
42+
{
43+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
44+
}
45+
46+
// The first element should be the generic type instantiation
47+
if (element.DataType != DATATYPE_GENERICINST)
48+
{
49+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
50+
}
51+
52+
// Advance to get the generic argument (T)
53+
if (FAILED(parser.Advance(element)))
54+
{
55+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
56+
}
57+
58+
if (element.DataType == DATATYPE_VALUETYPE)
59+
{
60+
// For value types we need to advance again
61+
if (FAILED(parser.Advance(element)))
62+
{
63+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
64+
}
65+
}
66+
67+
// check if T is a reference type or contains references
68+
NANOCLR_CHECK_HRESULT(RuntimeHelpers::CheckReferenceOrContainsReferences(
69+
element.Class,
70+
element.DataType,
71+
&parser,
72+
isRefContainsRefs));
73+
74+
if (isRefContainsRefs)
75+
{
76+
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
77+
}
78+
79+
// validate length parameter
80+
length = stack.Arg2().NumericByRefConst().s4;
81+
82+
if (length < 0)
83+
{
84+
NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
85+
}
86+
87+
// get the pointer to the array
88+
// assuming the pointer its an array allocated by a previous call to localloc
89+
sourceArray = stack.Arg1().DereferenceArray();
90+
91+
// check the element being UInt8
92+
if (sourceArray->m_typeOfElement != DATATYPE_U1)
93+
{
94+
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
95+
}
96+
97+
{
98+
// set reference to the pointer to the array
99+
thisSpan[FIELD___array].SetObjectReference(sourceArray);
100+
101+
// adjust the element type and size to match the generic type T
102+
// The sourceArray was allocated as byte[], but we're going to re-shaping it as T[]
103+
104+
// Get the TypeDef instance for the element type
105+
CLR_RT_TypeDef_Instance inst{};
106+
if (!inst.InitializeFromIndex(element.Class))
107+
{
108+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
109+
}
110+
111+
// Get the element data type and lookup table
112+
NanoCLRDataType dt = (NanoCLRDataType)inst.target->dataType;
113+
const CLR_RT_DataTypeLookup &dtl = c_CLR_RT_DataTypeLookup[dt];
114+
115+
CLR_UINT32 elementSize = dtl.m_sizeInBytes;
116+
117+
if (elementSize == CLR_RT_DataTypeLookup::c_NA)
118+
{
119+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
120+
}
121+
122+
CLR_UINT32 newNumElements = sourceArray->m_numOfElements / elementSize;
123+
124+
// Validate that length doesn't exceed available space
125+
if ((CLR_UINT32)length > newNumElements)
126+
{
127+
NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
128+
}
129+
130+
// Update the reflection data type to the new element type
131+
sourceArray->ReflectionData().data.type = element.Class;
132+
133+
// Now re-shape the array to make it T[]
134+
sourceArray->m_typeOfElement = dt;
135+
sourceArray->m_sizeOfElement = (CLR_UINT8)elementSize;
136+
sourceArray->m_numOfElements = (CLR_UINT32)length;
137+
138+
// Set fReference flag based on whether element type is numeric
139+
// (same logic as ExtractHeapBlocksForArray)
140+
sourceArray->m_fReference = (dtl.m_flags & CLR_RT_DataTypeLookup::c_Numeric) == 0;
141+
142+
// need to call this in order to have the individual elements cleared
143+
sourceArray->ClearElements(0, length);
144+
}
145+
146+
// set length
147+
thisSpan[FIELD___length].NumericByRef().s4 = length;
148+
149+
NANOCLR_NOCLEANUP();
150+
}
151+
9152
HRESULT Library_corlib_native_System_ReadOnlySpan_1::NativeReadOnlySpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4(
10153
CLR_RT_StackFrame &stack)
11154
{

src/CLR/CorLib/corlib_native_System_Span_1.cpp

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,149 @@
66

77
#include "CorLib.h"
88

9+
typedef Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers RuntimeHelpers;
10+
11+
HRESULT Library_corlib_native_System_Span_1::_ctor___VOID__VOIDptr__I4(CLR_RT_StackFrame &stack)
12+
{
13+
NANOCLR_HEADER();
14+
15+
int32_t length;
16+
bool isRefContainsRefs = false;
17+
18+
CLR_RT_HeapBlock_Array *sourceArray;
19+
20+
CLR_RT_HeapBlock *thisSpan = stack.This();
21+
22+
// grab caller to get the generic type
23+
CLR_RT_MethodDef_Instance &caller = stack.MethodCall();
24+
25+
if (caller.genericType == nullptr || !NANOCLR_INDEX_IS_VALID(*caller.genericType))
26+
{
27+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
28+
}
29+
30+
CLR_RT_TypeSpec_Instance typeSpec;
31+
if (!typeSpec.InitializeFromIndex(*caller.genericType))
32+
{
33+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
34+
}
35+
36+
CLR_RT_SignatureParser parser;
37+
parser.Initialize_TypeSpec(typeSpec);
38+
39+
CLR_RT_SignatureParser::Element element;
40+
41+
if (FAILED(parser.Advance(element)))
42+
{
43+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
44+
}
45+
46+
// The first element should be the generic type instantiation
47+
if (element.DataType != DATATYPE_GENERICINST)
48+
{
49+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
50+
}
51+
52+
// Advance to get the generic argument (T)
53+
if (FAILED(parser.Advance(element)))
54+
{
55+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
56+
}
57+
58+
if (element.DataType == DATATYPE_VALUETYPE)
59+
{
60+
// For value types we need to advance again
61+
if (FAILED(parser.Advance(element)))
62+
{
63+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
64+
}
65+
}
66+
67+
// check if T is a reference type or contains references
68+
NANOCLR_CHECK_HRESULT(RuntimeHelpers::CheckReferenceOrContainsReferences(
69+
element.Class,
70+
element.DataType,
71+
&parser,
72+
isRefContainsRefs));
73+
74+
if (isRefContainsRefs)
75+
{
76+
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
77+
}
78+
79+
// validate length parameter
80+
length = stack.Arg2().NumericByRefConst().s4;
81+
82+
if (length < 0)
83+
{
84+
NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
85+
}
86+
87+
// get the pointer to the array
88+
// assuming the pointer its an array allocated by a previous call to localloc
89+
sourceArray = stack.Arg1().DereferenceArray();
90+
91+
// check the element being UInt8
92+
if (sourceArray->m_typeOfElement != DATATYPE_U1)
93+
{
94+
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
95+
}
96+
97+
{
98+
// set reference to the pointer to the array
99+
thisSpan[FIELD___array].SetObjectReference(sourceArray);
100+
101+
// adjust the element type and size to match the generic type T
102+
// The sourceArray was allocated as byte[], but we're going to re-shaping it as T[]
103+
104+
// Get the TypeDef instance for the element type
105+
CLR_RT_TypeDef_Instance inst{};
106+
if (!inst.InitializeFromIndex(element.Class))
107+
{
108+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
109+
}
110+
111+
// Get the element data type and lookup table
112+
NanoCLRDataType dt = (NanoCLRDataType)inst.target->dataType;
113+
const CLR_RT_DataTypeLookup &dtl = c_CLR_RT_DataTypeLookup[dt];
114+
115+
CLR_UINT32 elementSize = dtl.m_sizeInBytes;
116+
117+
if (elementSize == CLR_RT_DataTypeLookup::c_NA)
118+
{
119+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
120+
}
121+
122+
CLR_UINT32 newNumElements = sourceArray->m_numOfElements / elementSize;
123+
124+
// Validate that length doesn't exceed available space
125+
if ((CLR_UINT32)length > newNumElements)
126+
{
127+
NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
128+
}
129+
130+
// Update the reflection data type to the new element type
131+
sourceArray->ReflectionData().data.type = element.Class;
132+
133+
// Now re-shape the array to make it T[]
134+
sourceArray->m_typeOfElement = dt;
135+
sourceArray->m_sizeOfElement = (CLR_UINT8)elementSize;
136+
sourceArray->m_numOfElements = (CLR_UINT32)length;
137+
138+
// Set fReference flag based on whether element type is numeric
139+
// (same logic as ExtractHeapBlocksForArray)
140+
sourceArray->m_fReference = (dtl.m_flags & CLR_RT_DataTypeLookup::c_Numeric) == 0;
141+
142+
// need to call this in order to have the individual elements cleared
143+
sourceArray->ClearElements(0, length);
144+
}
145+
146+
// set length
147+
thisSpan[FIELD___length].NumericByRef().s4 = length;
148+
149+
NANOCLR_NOCLEANUP();
150+
}
151+
9152
HRESULT Library_corlib_native_System_Span_1::CopyTo___VOID__SystemSpan_1(CLR_RT_StackFrame &stack)
10153
{
11154
NANOCLR_HEADER();

0 commit comments

Comments
 (0)