Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

implemented portable PInvoke infrastructure for CppCodeGen #4503

Merged
merged 1 commit into from
Sep 15, 2017
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
18 changes: 18 additions & 0 deletions src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,17 @@ private void ImportCall(ILOpcode opcode, int token)
return;
}

//this assumes that there will only ever be at most one RawPInvoke call in a given method
if (method.IsRawPInvoke())
{
AppendLine();
Append("PInvokeTransitionFrame __piframe");
AppendSemicolon();
AppendLine();
Append("__pinvoke(&__piframe)");
AppendSemicolon();
}

TypeDesc constrained = null;
if (opcode != ILOpcode.newobj)
{
Expand Down Expand Up @@ -1216,6 +1227,13 @@ private void ImportCall(ILOpcode opcode, int token)
PushExpression(retKind, temp, retType);
}
AppendSemicolon();

if (method.IsRawPInvoke())
{
AppendLine();
Append("__pinvoke_return(&__piframe)");
AppendSemicolon();
}
}

private void PassCallArguments(MethodSignature methodSignature, TypeDesc thisArgument)
Expand Down
17 changes: 16 additions & 1 deletion src/Native/Bootstrap/CppCodeGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,19 @@ inline double __uint64_to_double(uint64_t v)
return val.d;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can move ReversePInvokeFrame from common.h here as well while you are on it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Most of the CppCodeGen specific stuff should really be in this file actually and not in common.h.)


#endif // __CPP_CODE_GEN_H
struct ReversePInvokeFrame
{
void* m_savedPInvokeTransitionFrame;
void* m_savedThread;
};

struct PInvokeTransitionFrame
{
void* m_RIP;
void* m_FramePointer;
void* m_pThread; // unused by stack crawler, this is so GetThread is only called once per method
// can be an invalid pointer in universal transition cases (which never need to call GetThread)
uint32_t m_dwFlags; // PInvokeTransitionFrameFlags
uint64_t m_PreservedRegs[];
};
#endif
11 changes: 6 additions & 5 deletions src/Native/Bootstrap/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,16 @@ struct RawEEType
void* m_pIndirectionModule;
};

struct ReversePInvokeFrame
{
void* m_savedPInvokeTransitionFrame;
void* m_savedThread;
};
struct ReversePInvokeFrame;

void __reverse_pinvoke(ReversePInvokeFrame* pRevFrame);
void __reverse_pinvoke_return(ReversePInvokeFrame* pRevFrame);

struct PInvokeTransitionFrame;

void __pinvoke(PInvokeTransitionFrame* pFrame);
void __pinvoke_return(PInvokeTransitionFrame* pFrame);

typedef size_t UIntNative;

inline bool IS_ALIGNED(UIntNative val, UIntNative alignment)
Expand Down
13 changes: 13 additions & 0 deletions src/Native/Bootstrap/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,19 @@ void __reverse_pinvoke_return(ReversePInvokeFrame* pRevFrame)
RhpReversePInvokeReturn2(pRevFrame);
}

extern "C" void RhpPInvoke2(PInvokeTransitionFrame* pFrame);
extern "C" void RhpPInvokeReturn2(PInvokeTransitionFrame* pFrame);

void __pinvoke(PInvokeTransitionFrame* pFrame)
{
RhpPInvoke2(pFrame);
}

void __pinvoke_return(PInvokeTransitionFrame* pFrame)
{
RhpPInvokeReturn2(pFrame);
}

namespace System_Private_CoreLib { namespace System {

class Object {
Expand Down
15 changes: 15 additions & 0 deletions src/Native/Runtime/inc/rhbinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,20 @@ enum PInvokeTransitionFrameFlags
#pragma warning(push)
#pragma warning(disable:4200) // nonstandard extension used: zero-sized array in struct/union
class Thread;
#ifdef USE_PORTABLE_HELPERS
//the members of this structure are currently unused except m_pThread and exist only to allow compilation
//of StackFrameIterator their values are not currently being filled in and will require significant rework
//in order to satisfy the runtime requirements of StackFrameIterator
struct PInvokeTransitionFrame
{
void* m_RIP;
void* m_FramePointer;
Thread* m_pThread; // unused by stack crawler, this is so GetThread is only called once per method
// can be an invalid pointer in universal transition cases (which never need to call GetThread)
uint32_t m_dwFlags; // PInvokeTransitionFrameFlags
uint64_t m_PreservedRegs[];
};
#else
struct PInvokeTransitionFrame
{
#ifdef _TARGET_ARM_
Expand All @@ -646,6 +660,7 @@ struct PInvokeTransitionFrame
#endif
UIntTarget m_PreservedRegs[];
};
#endif //USE_PORTABLE_HELPERS
#pragma warning(pop)

#ifdef _TARGET_AMD64_
Expand Down
13 changes: 0 additions & 13 deletions src/Native/Runtime/portable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,19 +208,6 @@ COOP_PINVOKE_HELPER(Array *, RhpNewArrayAlign8, (EEType * pArrayEEType, int numE
}
#endif

//
// PInvoke
//
COOP_PINVOKE_HELPER(void, RhpPInvoke, (void* pFrame))
{
// TODO: RhpPInvoke
}

COOP_PINVOKE_HELPER(void, RhpPInvokeReturn, (void* pFrame))
{
// TODO: RhpPInvokeReturn
}

COOP_PINVOKE_HELPER(void, RhpInitialDynamicInterfaceDispatch, ())
{
ASSERT_UNCONDITIONALLY("NYI");
Expand Down
41 changes: 41 additions & 0 deletions src/Native/Runtime/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1158,6 +1158,31 @@ FORCEINLINE void Thread::InlineReversePInvokeReturn(ReversePInvokeFrame * pFrame
}
}

FORCEINLINE void Thread::InlinePInvoke(PInvokeTransitionFrame * pFrame)
{
pFrame->m_pThread = this;
// set our mode to preemptive
m_pTransitionFrame = pFrame;

// We need to prevent compiler reordering between above write and below read.
_ReadWriteBarrier();

// now check if we need to trap the thread
if (ThreadStore::IsTrapThreadsRequested())
{
RhpWaitForSuspend2();
}
}

FORCEINLINE void Thread::InlinePInvokeReturn(PInvokeTransitionFrame * pFrame)
{
m_pTransitionFrame = NULL;
if (ThreadStore::IsTrapThreadsRequested())
{
RhpWaitForGC2(pFrame);
}
}

Object * Thread::GetThreadAbortException()
{
return m_threadAbortException;
Expand Down Expand Up @@ -1287,4 +1312,20 @@ COOP_PINVOKE_HELPER(void, RhpReversePInvokeReturn2, (ReversePInvokeFrame * pFram
pFrame->m_savedThread->InlineReversePInvokeReturn(pFrame);
}

#ifdef USE_PORTABLE_HELPERS

COOP_PINVOKE_HELPER(void, RhpPInvoke2, (PInvokeTransitionFrame* pFrame))
{
Thread * pCurThread = ThreadStore::RawGetCurrentThread();
pCurThread->InlinePInvoke(pFrame);
}

COOP_PINVOKE_HELPER(void, RhpPInvokeReturn2, (PInvokeTransitionFrame* pFrame))
{
//reenter cooperative mode
pFrame->m_pThread->InlinePInvokeReturn(pFrame);
}

#endif //USE_PORTABLE_HELPERS

#endif // !DACCESS_COMPILE
3 changes: 3 additions & 0 deletions src/Native/Runtime/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,9 @@ class Thread : private ThreadBuffer
bool InlineTryFastReversePInvoke(ReversePInvokeFrame * pFrame);
void InlineReversePInvokeReturn(ReversePInvokeFrame * pFrame);

void InlinePInvoke(PInvokeTransitionFrame * pFrame);
void InlinePInvokeReturn(PInvokeTransitionFrame * pFrame);

Object * GetThreadAbortException();
void SetThreadAbortException(Object *exception);

Expand Down