Kaydet (Commit) 266c2d6b authored tarafından Tor Lillqvist's avatar Tor Lillqvist

More hacking on the wntmscx bridge, still far from ready

See asmbits.asm for some general comments and pointers to useful
information.
üst 7a042510
......@@ -87,13 +87,11 @@ static inline typelib_TypeClass cpp2uno_call(
}
}
// stack space
OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
// parameters
void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
void ** pCppArgs = pUnoArgs + nParams;
// indizes of values this have to be converted (interface conversion cpp<=>uno)
sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
sal_Int64 * pTempIndizes = (sal_Int64 *)(pUnoArgs + (2 * nParams));
// type descriptions for reconversions
typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
......@@ -116,7 +114,7 @@ static inline typelib_TypeClass cpp2uno_call(
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
case typelib_TypeClass_DOUBLE:
pCppStack += sizeof(sal_Int32); // extra long
pCppStack += sizeof(sal_Int64); // extra qword
break;
default:
break;
......@@ -155,7 +153,7 @@ static inline typelib_TypeClass cpp2uno_call(
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
}
pCppStack += sizeof(sal_Int32); // standard parameter length
pCppStack += sizeof(sal_Int64); // standard parameter length
}
// ExceptionHolder
......@@ -240,12 +238,10 @@ static inline typelib_TypeClass cpp2uno_call(
}
//==================================================================================================
static typelib_TypeClass __cdecl cpp_mediate(
typelib_TypeClass __cdecl cpp_mediate(
void ** pCallStack, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
sal_Int64 * pRegisterReturn /* space for register return */ )
{
OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
// pCallStack: ret adr, this, [ret *], params
void * pThis = static_cast< char * >(pCallStack[1]) - nVtableOffset;
bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
......@@ -361,74 +357,28 @@ static typelib_TypeClass __cdecl cpp_mediate(
return eRet;
}
//==================================================================================================
/**
* is called on incoming vtable calls
* (called by asm snippets)
*/
static __declspec(naked) void __cdecl cpp_vtable_call(void)
{
__asm
{
sub esp, 8 // space for immediate return type
push esp
push edx // vtable offset
push eax // function index
mov eax, esp
add eax, 20
push eax // original stack ptr
call cpp_mediate
add esp, 16
cmp eax, typelib_TypeClass_FLOAT
je Lfloat
cmp eax, typelib_TypeClass_DOUBLE
je Ldouble
cmp eax, typelib_TypeClass_HYPER
je Lhyper
cmp eax, typelib_TypeClass_UNSIGNED_HYPER
je Lhyper
// rest is eax
pop eax
add esp, 4
ret
Lhyper:
pop eax
pop edx
ret
Lfloat:
fld dword ptr [esp]
add esp, 8
ret
Ldouble:
fld qword ptr [esp]
add esp, 8
ret
}
}
extern void *cpp_vtable_call;
//==================================================================================================
int const codeSnippetSize = 16;
int const codeSnippetSize = 28;
unsigned char * codeSnippet(
unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset)
{
unsigned char * p = code;
OSL_ASSERT(sizeof (sal_Int32) == 4);
// mov eax, functionIndex:
// mov rax, functionIndex:
*p++ = 0xB8;
*reinterpret_cast< sal_Int32 * >(p) = functionIndex;
p += sizeof (sal_Int32);
// mov edx, vtableOffset:
*reinterpret_cast< sal_Int64 * >(p) = functionIndex;
p += sizeof (sal_Int64);
// mov rdx, vtableOffset:
*p++ = 0xBA;
*reinterpret_cast< sal_Int32 * >(p) = vtableOffset;
p += sizeof (sal_Int32);
// jmp rel32 cpp_vtable_call:
*reinterpret_cast< sal_Int64 * >(p) = vtableOffset;
p += sizeof (sal_Int64);
// jmp rel64 cpp_vtable_call:
*p++ = 0xE9;
*reinterpret_cast< sal_Int32 * >(p)
= ((unsigned char *) cpp_vtable_call) - p - sizeof (sal_Int32);
p += sizeof (sal_Int32);
*reinterpret_cast< sal_Int64 * >(p)
= ((unsigned char *) cpp_vtable_call) - p - sizeof (sal_Int64);
p += sizeof (sal_Int64);
OSL_ASSERT(p - code <= codeSnippetSize);
return code + codeSnippetSize;
}
......
......@@ -238,9 +238,9 @@ ObjectFunction::ObjectFunction( typelib_TypeDescription * pTypeDescr, void * fpF
*pCode++ = 0x68;
*(void **)pCode = this;
pCode += sizeof(void *);
// jmp rel32 fpFunc
// jmp rel64 fpFunc
*pCode++ = 0xe9;
*(sal_Int32 *)pCode = ((unsigned char *)fpFunc) - pCode - sizeof(sal_Int32);
*(sal_Int64 *)pCode = ((unsigned char *)fpFunc) - pCode - sizeof(sal_Int64);
}
//__________________________________________________________________________________________________
ObjectFunction::~ObjectFunction() throw ()
......@@ -249,47 +249,25 @@ ObjectFunction::~ObjectFunction() throw ()
}
//==================================================================================================
static void * __cdecl __copyConstruct( void * pExcThis, void * pSource, ObjectFunction * pThis )
void * __cdecl __copyConstruct( void * pExcThis, void * pSource, ObjectFunction * pThis )
throw ()
{
::uno_copyData( pExcThis, pSource, pThis->_pTypeDescr, cpp_acquire );
return pExcThis;
}
//==================================================================================================
static void * __cdecl __destruct( void * pExcThis, ObjectFunction * pThis )
void * __cdecl __destruct( void * pExcThis, ObjectFunction * pThis )
throw ()
{
::uno_destructData( pExcThis, pThis->_pTypeDescr, cpp_release );
return pExcThis;
}
// these are non virtual object methods; there is no this ptr on stack => ecx supplies _this_ ptr
//==================================================================================================
static __declspec(naked) void copyConstruct() throw ()
{
__asm
{
// ObjectFunction this already on stack
push [esp+8] // source exc object this
push ecx // exc object
call __copyConstruct
add esp, 12 // + ObjectFunction this
ret 4
}
}
//==================================================================================================
static __declspec(naked) void destruct() throw ()
{
__asm
{
// ObjectFunction this already on stack
push ecx // exc object
call __destruct
add esp, 8 // + ObjectFunction this
ret
}
}
// These are machine code snippets in asmbits.asm
extern void *copyConstruct;
extern void *destruct;
//==================================================================================================
struct ExceptionType
......@@ -332,9 +310,6 @@ RaiseInfo::RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ()
, _n3( 0 )
, _n4( 0 )
{
// a must be
OSL_ENSURE( sizeof(sal_Int32) == sizeof(ExceptionType *), "### pointer size differs from sal_Int32!" );
typelib_CompoundTypeDescription * pCompTypeDescr;
// info count
......@@ -346,10 +321,10 @@ RaiseInfo::RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ()
}
// info count accompanied by type info ptrs: type, base type, base base type, ...
_types = ::rtl_allocateMemory( sizeof(sal_Int32) + (sizeof(ExceptionType *) * nLen) );
*(sal_Int32 *)_types = nLen;
_types = ::rtl_allocateMemory( sizeof(sal_Int64) + (sizeof(ExceptionType *) * nLen) );
*(sal_Int64 *)_types = nLen;
ExceptionType ** ppTypes = (ExceptionType **)((sal_Int32 *)_types + 1);
ExceptionType ** ppTypes = (ExceptionType **)((sal_Int64 *)_types + 1);
sal_Int32 nPos = 0;
for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr;
......@@ -361,8 +336,8 @@ RaiseInfo::RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ()
//__________________________________________________________________________________________________
RaiseInfo::~RaiseInfo() throw ()
{
ExceptionType ** ppTypes = (ExceptionType **)((sal_Int32 *)_types + 1);
for ( sal_Int32 nTypes = *(sal_Int32 *)_types; nTypes--; )
ExceptionType ** ppTypes = (ExceptionType **)((sal_Int64 *)_types + 1);
for ( sal_Int32 nTypes = *(sal_Int64 *)_types; nTypes--; )
{
delete ppTypes[nTypes];
}
......@@ -486,14 +461,10 @@ void mscx_raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
void * pCppExc = alloca( pTypeDescr->nSize );
::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );
// a must be
OSL_ENSURE(
sizeof(sal_Int32) == sizeof(void *),
"### pointer size differs from sal_Int32!" );
DWORD arFilterArgs[3];
ULONG_PTR arFilterArgs[3];
arFilterArgs[0] = MSVC_magic_number;
arFilterArgs[1] = (DWORD)pCppExc;
arFilterArgs[2] = (DWORD)ExceptionInfos::getRaiseInfo( pTypeDescr );
arFilterArgs[1] = (ULONG_PTR)pCppExc;
arFilterArgs[2] = (ULONG_PTR)ExceptionInfos::getRaiseInfo( pTypeDescr );
// destruct uno exception
::uno_any_destruct( pUnoExc, 0 );
......@@ -514,13 +485,9 @@ int mscx_filterCppException(
if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode)
return EXCEPTION_CONTINUE_SEARCH;
#if _MSC_VER < 1300 // MSVC -6
bool rethrow = (pRecord->NumberParameters < 3 ||
pRecord->ExceptionInformation[ 2 ] == 0);
#else
bool rethrow = __CxxDetectRethrow( &pRecord );
OSL_ASSERT( pRecord == pPointers->ExceptionRecord );
#endif
if (rethrow && pRecord == pPointers->ExceptionRecord)
{
// hack to get msvcrt internal _curexception field:
......@@ -532,14 +499,12 @@ int mscx_filterCppException(
// crt\src\mtdll.h:
// offsetof (_tiddata, _curexception) -
// offsetof (_tiddata, _tpxcptinfoptrs):
#if _MSC_VER < 1300
0x18 // msvcrt,dll
#elif _MSC_VER < 1310
0x20 // msvcr70.dll
#elif _MSC_VER < 1400
0x24 // msvcr71.dll
#if _MSC_VER < 1500
error, this compiler version is not supported
#elif _MSC_VER < 1600
0x48 // msvcr90.dll
#else
0x28 // msvcr80.dll
error, please find value for this compiler version
#endif
);
}
......
......@@ -54,7 +54,8 @@ SLOFILES= \
$(SLO)$/cpp2uno.obj \
$(SLO)$/uno2cpp.obj \
$(SLO)$/dllinit.obj \
$(SLO)$/except.obj
$(SLO)$/except.obj \
$(SLO)$/asmbits.obj
NOOPTFILES= \
$(SLO)$/except.obj
......@@ -80,4 +81,3 @@ DEF1NAME=$(SHL1TARGET)
# --- Targets ------------------------------------------------------
.INCLUDE : target.mk
......@@ -47,106 +47,52 @@ using namespace ::com::sun::star::uno;
namespace
{
// As "long" is 32 bit also in x64 Windows we don't use "longs" in names
// to indicate pointer-sized stack slots etc like in the other x64 archs,
// but "qword" as in ml64.
//==================================================================================================
inline static void callVirtualMethod(
// In asmbits.asm
extern void callVirtualMethod(
void * pAdjustedThisPtr, sal_Int32 nVtableIndex,
void * pRegisterReturn, typelib_TypeClass eReturnTypeClass,
sal_Int32 * pStackLongs, sal_Int32 nStackLongs )
{
// parameter list is mixed list of * and values
// reference parameters are pointers
void * pReturn, typelib_TypeClass eReturnTypeClass,
sal_Int64 * pStack, sal_Int32 nStack,
sal_uInt64 *pGPR,
double *pFPR);
OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" );
OSL_ENSURE( (sizeof(void *) == 4) &&
(sizeof(sal_Int32) == 4), "### unexpected size of int!" );
__asm
#if OSL_DEBUG_LEVEL > 1
inline void callVirtualMethodwrapper(
void * pAdjustedThisPtr, sal_Int32 nVtableIndex,
void * pReturn, typelib_TypeDescriptionReference * pReturnTypeRef,
sal_Int64 * pStack, sal_Int32 nStack,
sal_uInt64 *pGPR, sal_uInt32 nGPR,
double *pFPR, sal_uInt32 nFPR)
{
// Let's figure out what is really going on here
{
mov eax, nStackLongs
test eax, eax
je Lcall
// copy values
mov ecx, eax
shl eax, 2 // sizeof(sal_Int32) == 4
add eax, pStackLongs // params stack space
Lcopy: sub eax, 4
push dword ptr [eax]
dec ecx
jne Lcopy
Lcall:
// call
mov ecx, pAdjustedThisPtr
push ecx // this ptr
mov edx, [ecx] // pvft
mov eax, nVtableIndex
shl eax, 2 // sizeof(void *) == 4
add edx, eax
call [edx] // interface method call must be __cdecl!!!
// register return
mov ecx, eReturnTypeClass
cmp ecx, typelib_TypeClass_VOID
je Lcleanup
mov ebx, pRegisterReturn
// int32
cmp ecx, typelib_TypeClass_LONG
je Lint32
cmp ecx, typelib_TypeClass_UNSIGNED_LONG
je Lint32
cmp ecx, typelib_TypeClass_ENUM
je Lint32
// int8
cmp ecx, typelib_TypeClass_BOOLEAN
je Lint8
cmp ecx, typelib_TypeClass_BYTE
je Lint8
// int16
cmp ecx, typelib_TypeClass_CHAR
je Lint16
cmp ecx, typelib_TypeClass_SHORT
je Lint16
cmp ecx, typelib_TypeClass_UNSIGNED_SHORT
je Lint16
// float
cmp ecx, typelib_TypeClass_FLOAT
je Lfloat
// double
cmp ecx, typelib_TypeClass_DOUBLE
je Ldouble
// int64
cmp ecx, typelib_TypeClass_HYPER
je Lint64
cmp ecx, typelib_TypeClass_UNSIGNED_HYPER
je Lint64
jmp Lcleanup // no simple type
Lint8:
mov byte ptr [ebx], al
jmp Lcleanup
Lint16:
mov word ptr [ebx], ax
jmp Lcleanup
Lfloat:
fstp dword ptr [ebx]
jmp Lcleanup
Ldouble:
fstp qword ptr [ebx]
jmp Lcleanup
Lint64:
mov dword ptr [ebx], eax
mov dword ptr [ebx+4], edx
jmp Lcleanup
Lint32:
mov dword ptr [ebx], eax
jmp Lcleanup
Lcleanup:
// cleanup stack (obsolete though because of function)
mov eax, nStackLongs
shl eax, 2 // sizeof(sal_Int32) == 4
add eax, 4 // this ptr
add esp, eax
fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR );
for ( unsigned int i = 0; i < nGPR; ++i )
fprintf( stderr, "0x%lx, ", pGPR[i] );
fprintf( stderr, "\nFPR's (%d): ", nFPR );
for ( unsigned int i = 0; i < nFPR; ++i )
fprintf( stderr, "%f, ", pFPR[i] );
fprintf( stderr, "\nStack (%d): ", nStack );
for ( unsigned int i = 0; i < nStack; ++i )
fprintf( stderr, "0x%lx, ", pStack[i] );
fprintf( stderr, "\n" );
}
callVirtualMethod( pAdjustedThisPtr, nVtableIndex,
pReturn, pReturnTypeRef->eTypeClass,
pStack, nStack,
pGPR,
pFPR);
}
#define callVirtualMethod callVirtualMethodwrapper
#endif
//==================================================================================================
static void cpp_call(
bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
......@@ -156,16 +102,33 @@ static void cpp_call(
void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) throw ()
{
// max space for: [complex ret ptr], values|ptr ...
char * pCppStack = (char *)alloca( sizeof(sal_Int32) + (nParams * sizeof(sal_Int64)) );
// (but will be used less - some of the values will be in pGPR and pFPR)
sal_uInt64 *pStack = (sal_uInt64 *) alloca( (nParams + 3) * sizeof(sal_uInt64) );
sal_uInt64 *pStackStart = pStack;
// Parameters to be passed in registers stored here
sal_uInt64 pGPR[4];
sal_uInt32 nGPR = 0;
double pFPR[4];
sal_uInt32 nFPR = 0;
if (nParams > 20)
{
}
char * pCppStack = (char *)alloca( sizeof(sal_Int64) + (nParams * sizeof(sal_Int64)) );
char * pCppStackStart = pCppStack;
// return
// Return
typelib_TypeDescription * pReturnTypeDescr = 0;
TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
bool bSimpleReturn = true;
if (pReturnTypeDescr)
{
if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
......@@ -186,15 +149,15 @@ static void cpp_call(
// stack space
OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
OSL_ENSURE( sizeof(void *) == sizeof(sal_Int64), "### unexpected size!" );
// args
void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
// indizes of values this have to be converted (interface conversion cpp<=>uno)
sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
// type descriptions for reconversions
typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
sal_Int32 nTempIndizes = 0;
sal_Int32 nTempIndizes = 0;
for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
{
......@@ -214,7 +177,7 @@ static void cpp_call(
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
case typelib_TypeClass_DOUBLE:
pCppStack += sizeof(sal_Int32); // extra long
pCppStack += sizeof(sal_Int64); // extra qword
break;
default:
break;
......@@ -254,7 +217,7 @@ static void cpp_call(
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
}
pCppStack += sizeof(sal_Int32); // standard parameter length
pCppStack += sizeof(sal_Int64); // standard parameter length
}
__try
......@@ -264,8 +227,8 @@ static void cpp_call(
reinterpret_cast< void ** >(pThis->getCppI()) + aVtableSlot.offset,
aVtableSlot.index,
pCppReturn, pReturnTypeDescr->eTypeClass,
(sal_Int32 *)pCppStackStart,
(pCppStack - pCppStackStart) / sizeof(sal_Int32) );
(sal_Int64 *)pCppStackStart,
(pCppStack - pCppStackStart) / sizeof(sal_Int64) );
}
__except (CPPU_CURRENT_NAMESPACE::mscx_filterCppException(
GetExceptionInformation(),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment