Skip to content
Open
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
19 changes: 18 additions & 1 deletion src/CLR/CorLib/corlib_native.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,10 @@ static const CLR_RT_MethodHandler method_lookup[] =
Library_corlib_native_System_Random::_ctor___VOID,
Library_corlib_native_System_Random::_ctor___VOID__I4,
nullptr,
Library_corlib_native_System_ReadOnlySpan_1::_ctor___VOID__VOIDptr__I4,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
Expand All @@ -711,6 +715,14 @@ static const CLR_RT_MethodHandler method_lookup[] =
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
Library_corlib_native_System_Reflection_ConstructorInfo::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN,
Library_corlib_native_System_Reflection_ConstructorInfo::Invoke___OBJECT__SZARRAY_OBJECT,
nullptr,
Expand Down Expand Up @@ -798,6 +810,7 @@ static const CLR_RT_MethodHandler method_lookup[] =
nullptr,
nullptr,
nullptr,
Library_corlib_native_System_Span_1::_ctor___VOID__VOIDptr__I4,
nullptr,
nullptr,
nullptr,
Expand Down Expand Up @@ -827,6 +840,10 @@ static const CLR_RT_MethodHandler method_lookup[] =
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
Library_corlib_native_System_Threading_AutoResetEvent::_ctor___VOID__BOOLEAN,
Library_corlib_native_System_Threading_AutoResetEvent::Reset___BOOLEAN,
Library_corlib_native_System_Threading_AutoResetEvent::Set___BOOLEAN,
Expand Down Expand Up @@ -1596,7 +1613,7 @@ const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib =

#if (NANOCLR_REFLECTION == TRUE)

0x3C34952A,
0xCECAB752,

#elif (NANOCLR_REFLECTION == FALSE)

Expand Down
2 changes: 2 additions & 0 deletions src/CLR/CorLib/corlib_native.h
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,7 @@ struct Library_corlib_native_System_ReadOnlySpan_1
static const int FIELD___array = 1;
static const int FIELD___length = 2;

NANOCLR_NATIVE_DECLARE(_ctor___VOID__VOIDptr__I4);
NANOCLR_NATIVE_DECLARE(NativeReadOnlySpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4);

//--//
Expand Down Expand Up @@ -962,6 +963,7 @@ struct Library_corlib_native_System_Span_1
static const int FIELD___array = 1;
static const int FIELD___length = 2;

NANOCLR_NATIVE_DECLARE(_ctor___VOID__VOIDptr__I4);
NANOCLR_NATIVE_DECLARE(CopyTo___VOID__SystemSpan_1);
NANOCLR_NATIVE_DECLARE(NativeSpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4);

Expand Down
108 changes: 108 additions & 0 deletions src/CLR/CorLib/corlib_native_System_ReadOnlySpan_1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,114 @@

#include "CorLib.h"

typedef Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers RuntimeHelpers;

HRESULT Library_corlib_native_System_ReadOnlySpan_1::_ctor___VOID__VOIDptr__I4(CLR_RT_StackFrame &stack)
{
NANOCLR_HEADER();

int32_t length;
bool isRefContainsRefs = false;
uintptr_t objectRawPointer;

CLR_RT_HeapBlock_Array *destinationArray;
CLR_RT_HeapBlock *thisSpan = stack.This();

// grab caller to get the generic type
CLR_RT_MethodDef_Instance &caller = stack.MethodCall();

if (caller.genericType == nullptr || !NANOCLR_INDEX_IS_VALID(*caller.genericType))
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}

CLR_RT_TypeSpec_Instance typeSpec;
if (!typeSpec.InitializeFromIndex(*caller.genericType))
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}

CLR_RT_SignatureParser parser;
parser.Initialize_TypeSpec(typeSpec);

CLR_RT_SignatureParser::Element element;

if (FAILED(parser.Advance(element)))
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}

// The first element should be the generic type instantiation
if (element.DataType != DATATYPE_GENERICINST)
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}

// Advance to get the generic argument (T)
if (FAILED(parser.Advance(element)))
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}

if (element.DataType == DATATYPE_VALUETYPE)
{
// For value types we need to advance again
if (FAILED(parser.Advance(element)))
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
}

// check if T is a reference type or contains references
NANOCLR_CHECK_HRESULT(
RuntimeHelpers::CheckReferenceOrContainsReferences(
element.Class,
element.DataType,
&parser,
isRefContainsRefs));

if (isRefContainsRefs)
{
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
}

// validate length parameter
length = stack.Arg2().NumericByRefConst().s4;

if (length < 0)
{
NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
}

// get the pointer to the array
// validate data type as being an unmanaged pointer
if (stack.Arg1().DataType() != DATATYPE_PTR)
{
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
}

objectRawPointer = (uintptr_t)stack.Arg1().UnmanagedPointer();

{
CLR_RT_HeapBlock &refArray = thisSpan[FIELD___array];
NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(refArray, length, element.Class));

CLR_RT_ProtectFromGC gc(refArray);

destinationArray = thisSpan[FIELD___array].DereferenceArray();
CLR_UINT32 elementSize = destinationArray->m_sizeOfElement;
CLR_UINT8 *elementPtr = destinationArray->GetFirstElement();

// copy data from the raw pointer to the newly created array
memcpy(elementPtr, (void *)objectRawPointer, elementSize * length);
}

// set length
thisSpan[FIELD___length].NumericByRef().s4 = length;

NANOCLR_NOCLEANUP();
}

HRESULT Library_corlib_native_System_ReadOnlySpan_1::NativeReadOnlySpanConstructor___VOID__SZARRAY_GENERICTYPE__I4__I4(
CLR_RT_StackFrame &stack)
{
Expand Down
108 changes: 108 additions & 0 deletions src/CLR/CorLib/corlib_native_System_Span_1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,114 @@

#include "CorLib.h"

typedef Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers RuntimeHelpers;

HRESULT Library_corlib_native_System_Span_1::_ctor___VOID__VOIDptr__I4(CLR_RT_StackFrame &stack)
{
NANOCLR_HEADER();

int32_t length;
bool isRefContainsRefs = false;
uintptr_t objectRawPointer;

CLR_RT_HeapBlock_Array *destinationArray;
CLR_RT_HeapBlock *thisSpan = stack.This();

// grab caller to get the generic type
CLR_RT_MethodDef_Instance &caller = stack.MethodCall();

if (caller.genericType == nullptr || !NANOCLR_INDEX_IS_VALID(*caller.genericType))
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}

CLR_RT_TypeSpec_Instance typeSpec;
if (!typeSpec.InitializeFromIndex(*caller.genericType))
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}

CLR_RT_SignatureParser parser;
parser.Initialize_TypeSpec(typeSpec);

CLR_RT_SignatureParser::Element element;

if (FAILED(parser.Advance(element)))
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}

// The first element should be the generic type instantiation
if (element.DataType != DATATYPE_GENERICINST)
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}

// Advance to get the generic argument (T)
if (FAILED(parser.Advance(element)))
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}

if (element.DataType == DATATYPE_VALUETYPE)
{
// For value types we need to advance again
if (FAILED(parser.Advance(element)))
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
}

// check if T is a reference type or contains references
NANOCLR_CHECK_HRESULT(
RuntimeHelpers::CheckReferenceOrContainsReferences(
element.Class,
element.DataType,
&parser,
isRefContainsRefs));

if (isRefContainsRefs)
{
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
}

// validate length parameter
length = stack.Arg2().NumericByRefConst().s4;

if (length < 0)
{
NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
}

// get the pointer to the array
// validate data type as being an unmanaged pointer
if (stack.Arg1().DataType() != DATATYPE_PTR)
{
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
}

objectRawPointer = (uintptr_t)stack.Arg1().UnmanagedPointer();

{
CLR_RT_HeapBlock &refArray = thisSpan[FIELD___array];
NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(refArray, length, element.Class));

CLR_RT_ProtectFromGC gc(refArray);

destinationArray = thisSpan[FIELD___array].DereferenceArray();
CLR_UINT32 elementSize = destinationArray->m_sizeOfElement;
CLR_UINT8 *elementPtr = destinationArray->GetFirstElement();

// copy data from the raw pointer to the newly created array
memcpy(elementPtr, (void *)objectRawPointer, elementSize * length);
}

// set length
thisSpan[FIELD___length].NumericByRef().s4 = length;

NANOCLR_NOCLEANUP();
}

HRESULT Library_corlib_native_System_Span_1::CopyTo___VOID__SystemSpan_1(CLR_RT_StackFrame &stack)
{
NANOCLR_HEADER();
Expand Down
34 changes: 34 additions & 0 deletions src/CLR/Core/CLR_RT_HeapBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,11 @@ HRESULT CLR_RT_HeapBlock::StoreToReference(CLR_RT_HeapBlock &ref, int size)
{
obj = &ref;
}
else if (dt == DATATYPE_PTR)
{
// unmanaged pointer, perform a direct memory copy
memcpy((void *)ref.UnmanagedPointer(), (void *)&NumericByRef(), size);
}
else
{
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
Expand Down Expand Up @@ -2073,6 +2078,20 @@ HRESULT CLR_RT_HeapBlock::NumericAdd(const CLR_RT_HeapBlock &right)
}
break;

case DATATYPE_PTR:
if (right.DataType() == DATATYPE_I4)
{
// binary numeric add (byte wise) (ECMA-335 Table III.2)
uint8_t *unmanagedPtr = (uint8_t *)UnmanagedPointer();
unmanagedPtr += right.NumericByRefConst().s4;

SetUnmanagedPointer((uintptr_t)unmanagedPtr);

break;
}
// fall through, can't add other types to a PTR
[[fallthrough]];

default:
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
Expand Down Expand Up @@ -2159,6 +2178,21 @@ HRESULT CLR_RT_HeapBlock::NumericSub(const CLR_RT_HeapBlock &right)
m_data.arrayReference.index -= right.m_data.numeric.s4 / array->m_sizeOfElement;
}
break;

case DATATYPE_PTR:
if (right.DataType() == DATATYPE_I4)
{
// binary numeric sub (byte wise) (ECMA-335 Table III.2)
uint8_t *unmanagedPtr = (uint8_t *)UnmanagedPointer();
unmanagedPtr -= right.NumericByRefConst().s4;

SetUnmanagedPointer((uintptr_t)unmanagedPtr);

break;
}
// fall through, can't subtract other types to a PTR
[[fallthrough]];

default:
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
}
Expand Down
Loading
Loading