Skip to content

Commit

Permalink
Add support for GetCustomAttributes
Browse files Browse the repository at this point in the history
- Add GetCurrent function to CLR_RT_AttributeEnumerator
- Fix bug in CLR_RT_AttributeEnumerator::Initialize
- Add code to support nanoframework/CoreLibrary#27

Signed-off-by: José Simões <jose.simoes@eclo.solutions>
  • Loading branch information
josesimoes committed Sep 28, 2018
1 parent 3db5016 commit 86614ca
Show file tree
Hide file tree
Showing 8 changed files with 214 additions and 2 deletions.
7 changes: 6 additions & 1 deletion src/CLR/CorLib/corlib_native.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,7 @@ static const CLR_RT_MethodHandler method_lookup[] =
NULL,
NULL,
NULL,
NULL,
Library_corlib_native_System_Reflection_MethodBase::get_Name___STRING,
Library_corlib_native_System_Reflection_MethodBase::get_DeclaringType___SystemType,
Library_corlib_native_System_Reflection_MethodBase::get_IsPublic___BOOLEAN,
Expand All @@ -581,12 +582,14 @@ static const CLR_RT_MethodHandler method_lookup[] =
Library_corlib_native_System_Reflection_MethodBase::Invoke___OBJECT__OBJECT__SZARRAY_OBJECT,
NULL,
NULL,
Library_corlib_native_System_Reflection_ConstructorInfo::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN,
Library_corlib_native_System_Reflection_ConstructorInfo::Invoke___OBJECT__SZARRAY_OBJECT,
NULL,
NULL,
NULL,
NULL,
Library_corlib_native_System_Reflection_FieldInfo::SetValue___VOID__OBJECT__OBJECT,
Library_corlib_native_System_Reflection_FieldInfo::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN,
NULL,
NULL,
NULL,
Expand All @@ -604,6 +607,7 @@ static const CLR_RT_MethodHandler method_lookup[] =
Library_corlib_native_System_Reflection_RuntimeFieldInfo::GetValue___OBJECT__OBJECT,
NULL,
Library_corlib_native_System_Reflection_RuntimeMethodInfo::get_ReturnType___SystemType,
Library_corlib_native_System_Reflection_RuntimeMethodInfo::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN,
NULL,
Library_corlib_native_System_Resources_ResourceManager::GetObjectInternal___OBJECT__I2,
Library_corlib_native_System_Resources_ResourceManager::GetObjectInternal___OBJECT__I2__I4__I4,
Expand Down Expand Up @@ -676,6 +680,7 @@ static const CLR_RT_MethodHandler method_lookup[] =
Library_corlib_native_System_RuntimeType::GetFields___SZARRAY_SystemReflectionFieldInfo__SystemReflectionBindingFlags,
Library_corlib_native_System_RuntimeType::GetInterfaces___SZARRAY_SystemType,
Library_corlib_native_System_RuntimeType::GetElementType___SystemType,
Library_corlib_native_System_RuntimeType::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN,
NULL,
NULL,
NULL,
Expand Down Expand Up @@ -940,7 +945,7 @@ static const CLR_RT_MethodHandler method_lookup[] =
const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib =
{
"mscorlib",
0x7F67F424,
0x8899664E,
method_lookup,
{ 1, 0, 0, 0 }
};
4 changes: 4 additions & 0 deletions src/CLR/CorLib/corlib_native.h
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,7 @@ struct Library_corlib_native_System_Reflection_MethodBase

struct Library_corlib_native_System_Reflection_ConstructorInfo
{
NANOCLR_NATIVE_DECLARE(GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN);
NANOCLR_NATIVE_DECLARE(Invoke___OBJECT__SZARRAY_OBJECT);

//--//
Expand All @@ -636,6 +637,7 @@ struct Library_corlib_native_System_Reflection_ConstructorInfo
struct Library_corlib_native_System_Reflection_FieldInfo
{
NANOCLR_NATIVE_DECLARE(SetValue___VOID__OBJECT__OBJECT);
NANOCLR_NATIVE_DECLARE(GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN);

//--//

Expand Down Expand Up @@ -666,6 +668,7 @@ struct Library_corlib_native_System_Reflection_RuntimeFieldInfo
struct Library_corlib_native_System_Reflection_RuntimeMethodInfo
{
NANOCLR_NATIVE_DECLARE(get_ReturnType___SystemType);
NANOCLR_NATIVE_DECLARE(GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN);

//--//

Expand Down Expand Up @@ -802,6 +805,7 @@ struct Library_corlib_native_System_RuntimeType
NANOCLR_NATIVE_DECLARE(GetFields___SZARRAY_SystemReflectionFieldInfo__SystemReflectionBindingFlags);
NANOCLR_NATIVE_DECLARE(GetInterfaces___SZARRAY_SystemType);
NANOCLR_NATIVE_DECLARE(GetElementType___SystemType);
NANOCLR_NATIVE_DECLARE(GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN);

//--//

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@
#include "CorLib.h"


HRESULT Library_corlib_native_System_Reflection_ConstructorInfo::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN( CLR_RT_StackFrame& stack )
{
NANOCLR_HEADER();

NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub());

NANOCLR_NOCLEANUP();
}

HRESULT Library_corlib_native_System_Reflection_ConstructorInfo::Invoke___OBJECT__SZARRAY_OBJECT( CLR_RT_StackFrame& stack )
{
NATIVE_PROFILE_CLR_CORE();
Expand Down
9 changes: 9 additions & 0 deletions src/CLR/CorLib/corlib_native_System_Reflection_FieldInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,12 @@ HRESULT Library_corlib_native_System_Reflection_FieldInfo::Initialize( CLR_RT_St

NANOCLR_NOCLEANUP();
}

HRESULT Library_corlib_native_System_Reflection_FieldInfo::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN( CLR_RT_StackFrame& stack )
{
NANOCLR_HEADER();

NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub());

NANOCLR_NOCLEANUP();
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,94 @@ HRESULT Library_corlib_native_System_Reflection_RuntimeMethodInfo::get_ReturnTyp

NANOCLR_NOCLEANUP();
}

HRESULT Library_corlib_native_System_Reflection_RuntimeMethodInfo::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN( CLR_RT_StackFrame& stack )
{
NATIVE_PROFILE_CLR_CORE();
NANOCLR_HEADER();

CLR_RT_HeapBlock* returnArray = NULL;
CLR_RT_MethodDef_Instance methodDefinition;
CLR_RT_SignatureParser signatureParser;
CLR_RT_TypeDescriptor desc;
CLR_RT_HeapBlock* callerMethod;
int count = 0;

// put the return array on the stack
CLR_RT_HeapBlock& top = stack.PushValueAndClear();

// get the caller method
callerMethod = stack.Arg0().Dereference();

NANOCLR_CHECK_HRESULT(Library_corlib_native_System_Reflection_MethodBase::GetMethodDescriptor( stack, *callerMethod, methodDefinition ));

signatureParser.Initialize_MethodSignature( methodDefinition.m_assm, methodDefinition.m_target );

NANOCLR_CHECK_HRESULT(desc.InitializeFromSignatureParser( signatureParser ));

// setup attribute enumerator
CLR_RT_AttributeEnumerator attributeEnumerator;
attributeEnumerator.Initialize( methodDefinition );

// 1st pass: count attributes
do
{
// move to the next attribute in the collection, if any
if(attributeEnumerator.Advance())
{
count++;
}
else
{
// done sweeping attributes

// create the result array
NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, count, g_CLR_RT_WellKnownTypes.m_TypeStatic ));

// use this to skip the 2nd pass if no attribute was found
if (count == 0) break;

// get the pointer to the first element
returnArray = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement();

// reset attribute enumerator
attributeEnumerator.Initialize( methodDefinition );

break;
}
}
while(true);

// 2nd pass: fill the array with the attributes types, if any
while(count > 0)
{
// move to the next attribute in the collection, if any
if(attributeEnumerator.Advance())
{
CLR_RT_TypeDef_Instance instanceTypeDef;
CLR_RT_HeapBlock* hbObj;

// get the type def for the current attribute
attributeEnumerator.GetCurrent(&instanceTypeDef);

CLR_RT_TypeDef_Index attributeType;
attributeType.Set(instanceTypeDef.Assembly(), instanceTypeDef.Type());

// create a new object for the attribute type and put it on the return array
NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*returnArray, g_CLR_RT_WellKnownTypes.m_TypeStatic));
hbObj = returnArray->Dereference();
// make sure the reflection is pointing to the attribute type
hbObj->SetReflection( attributeType );

returnArray++;
count--;
}
else
{
// no more attributes
break;
}
}

NANOCLR_NOCLEANUP();
}
84 changes: 84 additions & 0 deletions src/CLR/CorLib/corlib_native_System_RuntimeType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,87 @@ HRESULT Library_corlib_native_System_RuntimeType::GetName( CLR_RT_HeapBlock& arg

NANOCLR_NOCLEANUP();
}

HRESULT Library_corlib_native_System_RuntimeType::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN( CLR_RT_StackFrame& stack )
{
NATIVE_PROFILE_CLR_CORE();
NANOCLR_HEADER();

CLR_RT_HeapBlock* returnArray = NULL;
CLR_RT_HeapBlock* callerType = NULL;
CLR_RT_TypeDef_Instance instanceTypeDef;
CLR_RT_TypeDef_Instance typeDefinition;
CLR_RT_HeapBlock* hbObj;
int count = 0;

// put the return array on the stack
CLR_RT_HeapBlock& top = stack.PushValueAndClear();

// get the caller type
callerType = stack.Arg0().Dereference();

NANOCLR_CHECK_HRESULT(GetTypeDescriptor( *callerType, typeDefinition ));

// setup attribute enumerator
CLR_RT_AttributeEnumerator attributeEnumerator;
attributeEnumerator.Initialize( typeDefinition );

// 1st pass: count attributes
do
{
// move to the next attribute in the collection, if any
if(attributeEnumerator.Advance())
{
count++;
}
else
{
// done sweeping attributes

// create the result array
NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, count, g_CLR_RT_WellKnownTypes.m_TypeStatic ));

// use this to skip the 2nd pass if no attribute was found
if (count == 0) break;

// get the pointer to the first element
returnArray = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement();

// reset attribute enumerator
attributeEnumerator.Initialize( typeDefinition );

break;
}
}
while(true);

// 2nd pass: fill the array with the attributes types, if any
while(count > 0)
{
// move to the next attribute in the collection, if any
if(attributeEnumerator.Advance())
{
// get the type def for the current attribute
attributeEnumerator.GetCurrent(&instanceTypeDef);

CLR_RT_TypeDef_Index attributeType;
attributeType.Set(instanceTypeDef.Assembly(), instanceTypeDef.Type());

// create a new object for the attribute type and put it on the return array
NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*returnArray, g_CLR_RT_WellKnownTypes.m_TypeStatic));
hbObj = returnArray->Dereference();
// make sure the reflection is pointing to the attribute type
hbObj->SetReflection( attributeType );

returnArray++;
count--;
}
else
{
// no more attributes
break;
}
}

NANOCLR_NOCLEANUP();
}
10 changes: 9 additions & 1 deletion src/CLR/Core/TypeSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4160,7 +4160,7 @@ void CLR_RT_AttributeEnumerator::Initialize( const CLR_RT_FieldDef_Instance& ins
void CLR_RT_AttributeEnumerator::Initialize( const CLR_RT_MethodDef_Instance& inst )
{
NATIVE_PROFILE_CLR_CORE();
m_data.ownerType = TBL_FieldDef;
m_data.ownerType = TBL_MethodDef;
m_data.ownerIdx = inst.Method();

Initialize( inst.m_assm );
Expand Down Expand Up @@ -4210,6 +4210,14 @@ bool CLR_RT_AttributeEnumerator::Advance()
return fRes;
}

void CLR_RT_AttributeEnumerator::GetCurrent( CLR_RT_TypeDef_Instance* instTD )
{
CLR_RT_MethodDef_Instance md;

md.InitializeFromIndex ( m_match );
instTD->InitializeFromMethod( md );
}

bool CLR_RT_AttributeEnumerator::MatchNext( const CLR_RT_TypeDef_Instance* instTD, const CLR_RT_MethodDef_Instance* instMD )
{
NATIVE_PROFILE_CLR_CORE();
Expand Down
2 changes: 2 additions & 0 deletions src/CLR/Include/nanoCLR_Runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -1611,6 +1611,8 @@ struct CLR_RT_AttributeEnumerator

bool MatchNext( const CLR_RT_TypeDef_Instance* instTD, const CLR_RT_MethodDef_Instance* instMD );

void GetCurrent(CLR_RT_TypeDef_Instance* instTD);

private:
void Initialize( CLR_RT_Assembly* assm );
};
Expand Down

0 comments on commit 86614ca

Please sign in to comment.