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

Commit

Permalink
Implemented portable pinvoke infrastructure for CppCodeGen
Browse files Browse the repository at this point in the history
  • Loading branch information
hippiehunter committed Sep 15, 2017
1 parent aa725e1 commit 10698e4
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 19 deletions.
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;
}

#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

0 comments on commit 10698e4

Please sign in to comment.