diff options
author | Tor Lillqvist <tlillqvist@novell.com> | 2011-01-26 21:51:15 +0200 |
---|---|---|
committer | Tor Lillqvist <tlillqvist@novell.com> | 2011-01-26 23:08:54 +0200 |
commit | a6d80f95edfa9dd1b3f112c0c5d81aa19f8a533f (patch) | |
tree | 67787ec18531c6dd3eca2de751c10497ca5850c3 /bridges | |
parent | c7237caae9243080de1e325b2751951886800b59 (diff) |
Intermediate commit
Diffstat (limited to 'bridges')
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx | 170 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx | 3 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx | 23 |
3 files changed, 157 insertions, 39 deletions
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx index de8ceca10..7c8831a2d 100644 --- a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx @@ -90,12 +90,12 @@ static inline typelib_TypeClass cpp2uno_call( // 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_Int64 * pTempIndizes = (sal_Int64 *)(pUnoArgs + (2 * nParams)); + // indexes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int64 * pTempIndexes = (sal_Int64 *)(pUnoArgs + (2 * nParams)); // type descriptions for reconversions typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); - sal_Int32 nTempIndizes = 0; + sal_Int32 nTempIndexes = 0; for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) { @@ -130,9 +130,9 @@ static inline typelib_TypeClass cpp2uno_call( { // uno out is unconstructed mem! pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); - pTempIndizes[nTempIndizes] = nPos; + pTempIndexes[nTempIndexes] = nPos; // will be released at reconversion - ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + ppTempParamTypeDescr[nTempIndexes++] = pParamTypeDescr; } // is in/inout else if (bridges::cpp_uno::shared::relatesToInterfaceType( @@ -142,9 +142,9 @@ static inline typelib_TypeClass cpp2uno_call( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), *(void **)pCppStack, pParamTypeDescr, pThis->getBridge()->getCpp2Uno() ); - pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + pTempIndexes[nTempIndexes] = nPos; // has to be reconverted // will be released at reconversion - ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + ppTempParamTypeDescr[nTempIndexes++] = pParamTypeDescr; } else // direct way { @@ -168,15 +168,15 @@ static inline typelib_TypeClass cpp2uno_call( if (pUnoExc) { // destruct temporary in/inout params - while (nTempIndizes--) + while (nTempIndexes--) { - sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + sal_Int32 nIndex = pTempIndexes[nTempIndexes]; if (pParams[nIndex].bIn) // is in/inout => was constructed { - ::uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + ::uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndexes], 0 ); } - TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndexes] ); } if (pReturnTypeDescr) { @@ -192,10 +192,10 @@ static inline typelib_TypeClass cpp2uno_call( else // else no exception occurred... { // temporary params - while (nTempIndizes--) + while (nTempIndexes--) { - sal_Int32 nIndex = pTempIndizes[nTempIndizes]; - typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + sal_Int32 nIndex = pTempIndexes[nTempIndexes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndexes]; if (pParams[nIndex].bOut) // inout/out { @@ -362,31 +362,75 @@ extern void *cpp_vtable_call; //================================================================================================== int const codeSnippetSize = 28; -#if 0 +// This function generates the code that acts as a proxy for the UNO function to be called. +// The generated code does the following: +// - Save register parametrs. unsigned char * codeSnippet( unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset) { unsigned char * p = code; - // mov rax, functionIndex: + + // mov eax, functionIndex: *p++ = 0xB8; - *reinterpret_cast< sal_Int64 * >(p) = functionIndex; - p += sizeof (sal_Int64); - // mov rdx, vtableOffset: + *reinterpret_cast< sal_Int32 * >(p) = functionIndex; + p += sizeof (sal_Int32); + + // mov edx, vtableOffset: *p++ = 0xBA; - *reinterpret_cast< sal_Int64 * >(p) = vtableOffset; - p += sizeof (sal_Int64); + *reinterpret_cast< sal_Int32 * >(p) = vtableOffset; + p += sizeof (sal_Int32); + +#if 0 + 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 + +#endif + +#if 0 // jmp rel64 cpp_vtable_call: *p++ = 0xE9; *reinterpret_cast< sal_Int64 * >(p) = ((unsigned char *) cpp_vtable_call) - p - sizeof (sal_Int64); p += sizeof (sal_Int64); +#endif OSL_ASSERT(p - code <= codeSnippetSize); return code + codeSnippetSize; } -#endif - } struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; @@ -437,18 +481,88 @@ static void whatthefuck(sal_Int64 i, ...) unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( Slot ** slots, unsigned char * code, - typelib_InterfaceTypeDescription const *, sal_Int32 functionOffset, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, sal_Int32 functionCount, sal_Int32 vtableOffset) { (*slots) -= functionCount; Slot * s = *slots; - for (sal_Int32 i = 0; i < functionCount; ++i) { + + for (int i = 0; i < functionCount; ++i) { + typelib_TypeDescription * pTD = 0; + + TYPELIB_DANGER_GET( &pTD, type->ppMembers[ i ] ); + OSL_ASSERT( pTD ); + + CPPU_CURRENT_NAMESPACE::RegParamKind param_kind[4]; + int nr = 0; + + if ( pTD->eTypeClass == typelib_TypeClass_INTERFACE_ATTRIBUTE ) + { + typelib_InterfaceAttributeTypeDescription *pAttrTD = + reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD ); + + // get method +#if 0 + (s++)->fn = code; + code = codeSnippet(code, functionOffset++, vtableOffset); +#else + (s++)->fn = whatthefuck; +#endif + + if ( ! pAttrTD->bReadOnly ) + { + // set method +#if 0 + (s++)->fn = code; + code = codeSnippet(code, functionOffset++, vtableOffset); +#else + (s++)->fn = whatthefuck; +#endif + } + } + else if ( pTD->eTypeClass == typelib_TypeClass_INTERFACE_METHOD ) + { + typelib_InterfaceMethodTypeDescription *pMethodTD = + reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD ); + + typelib_TypeDescription *pReturnTD = 0; + TYPELIB_DANGER_GET( &pReturnTD, pMethodTD->pReturnTypeRef ); + OSL_ASSERT( pReturnTD ); + + if ( pReturnTD->nSize > 8 ) { + // Hidden return value + param_kind[nr++] = CPPU_CURRENT_NAMESPACE::REGPARAM_INT; + } + TYPELIB_DANGER_RELEASE( pReturnTD ); + + // 'this' + param_kind[nr++] = CPPU_CURRENT_NAMESPACE::REGPARAM_INT; + + for (int j = 0; nr < 4 && j < pMethodTD->nParams; ++j) + { + typelib_TypeDescription *pParamTD = 0; + + TYPELIB_DANGER_GET( &pParamTD, pMethodTD->pParams[j].pTypeRef ); + OSL_ASSERT( pParamTD ); + + if ( pParamTD->eTypeClass == typelib_TypeClass_FLOAT || + pParamTD->eTypeClass == typelib_TypeClass_DOUBLE ) + param_kind[nr++] = CPPU_CURRENT_NAMESPACE::REGPARAM_FLT; + else + param_kind[nr++] = CPPU_CURRENT_NAMESPACE::REGPARAM_INT; + + TYPELIB_DANGER_RELEASE( pParamTD ); + #if 0 - (s++)->fn = code; - code = codeSnippet(code, functionOffset++, vtableOffset); + (s++)->fn = code; + code = codeSnippet(code, functionOffset++, vtableOffset); #else - (s++)->fn = whatthefuck; + (s++)->fn = whatthefuck; #endif + } + } + else + OSL_ASSERT( false ); } return code; } diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx b/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx index abf99f76a..87d7f3fed 100644 --- a/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx @@ -43,6 +43,9 @@ namespace CPPU_CURRENT_NAMESPACE const DWORD MSVC_ExceptionCode = 0xe06d7363; const long MSVC_magic_number = 0x19930520L; +typedef enum { REGPARAM_INT, REGPARAM_FLT } RegParamKind; + + //============================================================================== type_info * mscx_getRTTI( ::rtl::OUString const & rUNOname ); diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx index 2ce275a6a..92be09d3d 100644 --- a/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx @@ -223,19 +223,20 @@ static void cpp_call( // The Windows x64 calling convention is very regular and // elegant (even if perhaps then slightly slower than the // Linux x64 one): The first four parameters, never more, are - // passed in registers, as long as they are a qword ins size + // passed in registers, as long as they are a qword in size // or less. (If larger, a pointer to a temp copy is passed, so // it's equivalent anyway.) Floating point values are passed - // in XMM0..3 register, others in RCX, RDX, R8, R9. Now, the - // nice thing for us is that for varargs functions, - // floating-point parameters among the four first ones are - // always passed *both* in XMM and integer registers. So we - // don't need to bother here calling the method different ways - // depending on what types of parameters it actually expects, - // just pretend parameters 3..4 are doubles and they will be - // passed both in XMM and integer registers, callee will find - // them where it expects. (The callee is not actually varargs, - // of course.) + // in XMM0..3 registers, others in RCX, RDX, R8, R9. + + // Now, the nice thing for us is that when calling varargs + // functions, floating-point parameters among the four first + // ones are always passed *both* in an XMM and integer + // register. So we don't need to bother here calling the + // method different ways depending on what types of parameters + // it actually expects. We just pretend parameters 3..4 are + // doubles, and they will be passed both in XMM and integer + // registers, and the callee will find them where it + // expects. (The callee is not actually varargs, of course.) sal_Int64 (*pMethod)(sal_Int64, ...) = (sal_Int64 (*)(sal_Int64, ...)) |