Kaydet (Commit) 9540af1e authored tarafından Tor Lillqvist's avatar Tor Lillqvist

Start of C++/UNO bridge for iOS simulator and device

Unlikely to work yet, but at least builds for the simulator.

We can not use dynamic code generation on iOS, so we use a fixed set
of code snippets, genertated by a Perl script. Experimentation seems
to indicate that a relatively small set of static code snippets should
be enough in simple use cases with no extensions (that we can't really
support on iOS anyway) and stuff.

Except for the static set of snippets the code mostly is, or will be,
an ifdefified combination of the gcc3_linux_arm and gcc3_macosx_intel
code. The ABI on iOS ARM devices should be quite close to that on
Linux ARM, knock on wood.
üst 2ba07916
...@@ -22,6 +22,7 @@ br bridges\source\cpp_uno\gcc3_linux_hppa nmake - u br_gcc3lh br_unotypes NULL ...@@ -22,6 +22,7 @@ br bridges\source\cpp_uno\gcc3_linux_hppa nmake - u br_gcc3lh br_unotypes NULL
br bridges\source\cpp_uno\gcc3_linux_alpha nmake - u br_gcc3ll br_unotypes NULL br bridges\source\cpp_uno\gcc3_linux_alpha nmake - u br_gcc3ll br_unotypes NULL
br bridges\source\cpp_uno\gcc3_macosx_intel nmake - u br_gcc3macoxi br_cppuno_shared br_unotypes br_inc NULL br bridges\source\cpp_uno\gcc3_macosx_intel nmake - u br_gcc3macoxi br_cppuno_shared br_unotypes br_inc NULL
br bridges\source\cpp_uno\gcc3_macosx_powerpc nmake - u br_gcc3macoxp br_cppuno_shared br_unotypes br_inc NULL br bridges\source\cpp_uno\gcc3_macosx_powerpc nmake - u br_gcc3macoxp br_cppuno_shared br_unotypes br_inc NULL
br bridges\source\cpp_uno\gcc3_ios_arm nmake - u br_gcc3iosr br_cppuno_shared br_unotypes br_inc NULL
br bridges\source\cpp_uno\cc50_solaris_sparc nmake - u br_cc50sols br_unotypes br_cppuno_shared br_inc NULL br bridges\source\cpp_uno\cc50_solaris_sparc nmake - u br_cc50sols br_unotypes br_cppuno_shared br_inc NULL
br bridges\source\cpp_uno\cc5_solaris_sparc64 nmake - u br_cc5sols64 br_unotypes br_cppuno_shared br_inc NULL br bridges\source\cpp_uno\cc5_solaris_sparc64 nmake - u br_cc5sols64 br_unotypes br_cppuno_shared br_inc NULL
br bridges\source\cpp_uno\cc50_solaris_intel nmake - u br_cc50soli br_unotypes br_cppuno_shared br_inc NULL br bridges\source\cpp_uno\cc50_solaris_intel nmake - u br_cc50soli br_unotypes br_cppuno_shared br_inc NULL
......
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_bridges.hxx"
#include <com/sun/star/uno/genfunc.hxx>
#include "com/sun/star/uno/RuntimeException.hpp"
#include "com/sun/star/uno/Sequence.hxx"
#include <uno/data.h>
#include <typelib/typedescription.hxx>
#include "bridges/cpp_uno/shared/bridge.hxx"
#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
#include "bridges/cpp_uno/shared/types.hxx"
#include "bridges/cpp_uno/shared/vtablefactory.hxx"
#include "share.hxx"
#include "boost/static_assert.hpp"
#include <stdio.h>
using namespace ::com::sun::star::uno;
namespace
{
//==================================================================================================
void cpp2uno_call(
bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
const typelib_TypeDescription * pMemberTypeDescr,
typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
sal_Int32 nParams, typelib_MethodParameter * pParams,
void ** pCallStack,
void * pReturnValue )
{
// pCallStack: ret, [return ptr], this, params
char * pCppStack = (char *)(pCallStack +1);
// return
typelib_TypeDescription * pReturnTypeDescr = 0;
if (pReturnTypeRef)
TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
void * pUnoReturn = 0;
void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
if (pReturnTypeDescr)
{
// xxx todo: test PolyStructy<STRUCT<long>> foo()
if (CPPU_CURRENT_NAMESPACE::isSimpleReturnType( pReturnTypeDescr ))
{
pUnoReturn = pReturnValue; // direct way for simple types
}
else // complex return via ptr (pCppReturn)
{
pCppReturn = *(void **)pCppStack;
pCppStack += sizeof(void *);
pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(
pReturnTypeDescr )
? alloca( pReturnTypeDescr->nSize )
: pCppReturn); // direct way
}
}
// pop this
pCppStack += sizeof( void* );
// 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));
// type descriptions for reconversions
typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
sal_Int32 nTempIndizes = 0;
for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
{
const typelib_MethodParameter & rParam = pParams[nPos];
typelib_TypeDescription * pParamTypeDescr = 0;
TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
if (!rParam.bOut
&& bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
// value
{
pCppArgs[nPos] = pCppStack;
pUnoArgs[nPos] = pCppStack;
switch (pParamTypeDescr->eTypeClass)
{
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
case typelib_TypeClass_DOUBLE:
pCppStack += sizeof(sal_Int32); // extra long
default:
break;
}
// no longer needed
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
else // ptr to complex value | ref
{
pCppArgs[nPos] = *(void **)pCppStack;
if (! rParam.bIn) // is pure out
{
// uno out is unconstructed mem!
pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
pTempIndizes[nTempIndizes] = nPos;
// will be released at reconversion
ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
}
// is in/inout
else if (bridges::cpp_uno::shared::relatesToInterfaceType(
pParamTypeDescr ))
{
uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
*(void **)pCppStack, pParamTypeDescr,
pThis->getBridge()->getCpp2Uno() );
pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
// will be released at reconversion
ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
}
else // direct way
{
pUnoArgs[nPos] = *(void **)pCppStack;
// no longer needed
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
}
pCppStack += sizeof(sal_Int32); // standard parameter length
}
// ExceptionHolder
uno_Any aUnoExc; // Any will be constructed by callee
uno_Any * pUnoExc = &aUnoExc;
// invoke uno dispatch call
(*pThis->getUnoI()->pDispatcher)(
pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
// in case an exception occurred...
if (pUnoExc)
{
// destruct temporary in/inout params
for ( ; nTempIndizes--; )
{
sal_Int32 nIndex = pTempIndizes[nTempIndizes];
if (pParams[nIndex].bIn) // is in/inout => was constructed
uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
}
if (pReturnTypeDescr)
TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
CPPU_CURRENT_NAMESPACE::raiseException(
&aUnoExc, pThis->getBridge()->getUno2Cpp() );
// has to destruct the any
}
else // else no exception occurred...
{
// temporary params
for ( ; nTempIndizes--; )
{
sal_Int32 nIndex = pTempIndizes[nTempIndizes];
typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
if (pParams[nIndex].bOut) // inout/out
{
// convert and assign
uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
pThis->getBridge()->getUno2Cpp() );
}
// destroy temp uno param
uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
// return
if (pCppReturn) // has complex return
{
if (pUnoReturn != pCppReturn) // needs reconversion
{
uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
pThis->getBridge()->getUno2Cpp() );
// destroy temp uno return
uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
}
if (pReturnValue != pCppReturn) {
// complex return ptr is set to eax if return value
// is not transferred via eax[/edx]:
*static_cast< void ** >(pReturnValue) = pCppReturn;
}
}
if (pReturnTypeDescr)
{
TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
}
}
}
//==================================================================================================
extern "C" void cpp_vtable_call(
int nFunctionIndex, int nVtableOffset, void** pCallStack,
void * pReturnValue )
{
OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
// pCallStack: ret adr, [ret *], this, params
void * pThis;
if( nFunctionIndex & 0x80000000 )
{
nFunctionIndex &= 0x7fffffff;
pThis = pCallStack[2];
}
else
{
pThis = pCallStack[1];
}
pThis = static_cast< char * >(pThis) - nVtableOffset;
bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
= bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
pThis);
#if OSL_DEBUG_LEVEL > 1
fprintf( stderr, "%p %p %p pThis=%p, pCppI=%p, function index=%d, vtable offset=%d\n", pCallStack[0], pCallStack[1], pCallStack[2], pThis, pCppI, nFunctionIndex, nVtableOffset );
#endif
typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
#if OSL_DEBUG_LEVEL > 1
fprintf( stderr, "name=%s\n", rtl::OUStringToOString(pTypeDescr->aBase.pTypeName, RTL_TEXTENCODING_UTF8).getStr() );
#endif
OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
{
throw RuntimeException(
rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )),
(XInterface *)pThis );
}
// determine called method
sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
#if OSL_DEBUG_LEVEL > 1
fprintf(stderr, "calling %s\n", rtl::OUStringToOString(aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_UTF8).getStr());
#endif
switch (aMemberDescr.get()->eTypeClass)
{
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
{
if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
{
// is GET method
cpp2uno_call(
pCppI, aMemberDescr.get(),
((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
0, 0, // no params
pCallStack, pReturnValue );
}
else
{
// is SET method
typelib_MethodParameter aParam;
aParam.pTypeRef =
((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
aParam.bIn = sal_True;
aParam.bOut = sal_False;
cpp2uno_call(
pCppI, aMemberDescr.get(),
0, // indicates void return
1, &aParam,
pCallStack, pReturnValue );
}
break;
}
case typelib_TypeClass_INTERFACE_METHOD:
{
// is METHOD
switch (nFunctionIndex)
{
case 1: // acquire()
pCppI->acquireProxy(); // non virtual call!
break;
case 2: // release()
pCppI->releaseProxy(); // non virtual call!
break;
case 0: // queryInterface() opt
{
typelib_TypeDescription * pTD = 0;
TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->getTypeLibType() );
if (pTD)
{
XInterface * pInterface = 0;
(*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
pCppI->getBridge()->getCppEnv(),
(void **)&pInterface, pCppI->getOid().pData,
(typelib_InterfaceTypeDescription *)pTD );
if (pInterface)
{
::uno_any_construct(
reinterpret_cast< uno_Any * >( pCallStack[1] ),
&pInterface, pTD, cpp_acquire );
pInterface->release();
TYPELIB_DANGER_RELEASE( pTD );
*static_cast< void ** >(pReturnValue) = pCallStack[1];
break;
}
TYPELIB_DANGER_RELEASE( pTD );
}
} // else perform queryInterface()
default:
cpp2uno_call(
pCppI, aMemberDescr.get(),
((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
pCallStack, pReturnValue );
}
break;
}
default:
{
throw RuntimeException(
rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )),
(XInterface *)pThis );
}
}
}
//==================================================================================================
extern "C" {
extern int nFunIndexes, nVtableOffsets;
extern unsigned char **codeSnippets;
}
unsigned char * codeSnippet(
sal_Int32 functionIndex, sal_Int32 vtableOffset,
#ifdef __arm
bool bHasHiddenParam
#else
typelib_TypeDescriptionReference * pReturnTypeRef
#endif
)
{
OSL_ASSERT(functionIndex < nFunIndexes);
if (!(functionIndex < nFunIndexes))
return NULL;
OSL_ASSERT(vtableOffset < nVtableOffsets);
if (!(vtableOffset < nVtableOffsets))
return NULL;
#ifdef __arm
return codeSnippets[functionIndex*nVtableOffsets*2 + vtableOffset*2 + bHasHiddenParam];
#else
enum { General, Void, Hyper, Float, Double, Class } exec;
int flag = 0;
if (pReturnTypeRef == 0) {
exec = Void;
}
else {
switch (pReturnTypeRef->eTypeClass) {
case typelib_TypeClass_VOID:
exec = Void;
break;
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
exec = Hyper;
break;
case typelib_TypeClass_FLOAT:
exec = Float;
break;
case typelib_TypeClass_DOUBLE:
exec = Double;
break;
case typelib_TypeClass_STRUCT:
case typelib_TypeClass_EXCEPTION: {
typelib_TypeDescription * pReturnTypeDescr = 0;
TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
bool const bSimpleReturnStruct =
CPPU_CURRENT_NAMESPACE::isSimpleReturnType(pReturnTypeDescr);
sal_Int32 const nRetSize = pReturnTypeDescr->nSize;
TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
if (bSimpleReturnStruct && nRetSize <= 8) {
exec = General; // fills eax
if (nRetSize > 4)
exec = Hyper; // fills eax/edx
break;
}
}
case typelib_TypeClass_STRING:
case typelib_TypeClass_TYPE:
case typelib_TypeClass_SEQUENCE:
case typelib_TypeClass_INTERFACE:
case typelib_TypeClass_ANY:
flag = 1;
exec = Class;
break;
default:
exec = General;
break;
}
}
return codeSnippets[functionIndex*nVtableOffsets*6*2 + vtableOffset*6*2 + exec*2 + flag];
#endif
}
}
struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
bridges::cpp_uno::shared::VtableFactory::Slot *
bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
{
return static_cast< Slot * >(block) + 2;
}
sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
sal_Int32 slotCount)
{
return 0;
}
bridges::cpp_uno::shared::VtableFactory::Slot *
bridges::cpp_uno::shared::VtableFactory::initializeBlock(
void * block, sal_Int32 slotCount)
{
Slot * slots = mapBlockToVtable(block);
slots[-2].fn = 0;
slots[-1].fn = 0;
return slots + slotCount;
}
unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
Slot ** slots, unsigned char * code,
typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
sal_Int32 functionCount, sal_Int32 vtableOffset)
{
(*slots) -= functionCount;
Slot * s = *slots;
for (sal_Int32 i = 0; i < type->nMembers; ++i) {
typelib_TypeDescription * member = 0;
TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
OSL_ASSERT(member != 0);
switch (member->eTypeClass) {
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
#ifdef __arm
typelib_InterfaceAttributeTypeDescription *pAttrTD =
reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( member );
#endif
// Getter:
(s++)->fn = codeSnippet(
functionOffset++, vtableOffset,
#ifdef __arm
arm::return_in_hidden_param( pAttrTD->pAttributeTypeRef )
#else
reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >(
member)->pAttributeTypeRef
#endif
);
// Setter:
if (!reinterpret_cast<
typelib_InterfaceAttributeTypeDescription * >(
member)->bReadOnly)
{
(s++)->fn = codeSnippet(
functionOffset++, vtableOffset,
#ifdef __arm
false
#else
0 /* indicates VOID */
#endif
);
}
break;
case typelib_TypeClass_INTERFACE_METHOD:
#ifdef __arm
typelib_InterfaceMethodTypeDescription *pMethodTD =
reinterpret_cast<
typelib_InterfaceMethodTypeDescription * >(member);
#endif
(s++)->fn = codeSnippet(
functionOffset++, vtableOffset,
#ifdef __arm
arm::return_in_hidden_param(pMethodTD->pReturnTypeRef)
#else
reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(
member)->pReturnTypeRef
#endif
);
break;
default:
OSL_ASSERT(false);
break;
}
TYPELIB_DANGER_RELEASE(member);
}
return code;
}
void bridges::cpp_uno::shared::VtableFactory::flushCode(
unsigned char const *, unsigned char const *)
{}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_bridges.hxx"
#include <stdio.h>
#include <dlfcn.h>
#include <cxxabi.h>
#include <boost/unordered_map.hpp>
#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include <osl/diagnose.h>
#include <osl/mutex.hxx>
#include <com/sun/star/uno/genfunc.hxx>
#include "com/sun/star/uno/RuntimeException.hpp"
#include <typelib/typedescription.hxx>
#include <uno/any2.h>
#include "share.hxx"
using namespace ::std;
using namespace ::osl;
using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::__cxxabiv1;
namespace CPPU_CURRENT_NAMESPACE
{
void dummy_can_throw_anything( char const * )
{
}
//==================================================================================================
static OUString toUNOname( char const * p ) SAL_THROW( () )
{
#if OSL_DEBUG_LEVEL > 1
char const * start = p;
#endif
// example: N3com3sun4star4lang24IllegalArgumentExceptionE
OUStringBuffer buf( 64 );
OSL_ASSERT( 'N' == *p );
++p; // skip N
while ('E' != *p)
{
// read chars count
long n = (*p++ - '0');
while ('0' <= *p && '9' >= *p)
{
n *= 10;
n += (*p++ - '0');
}
buf.appendAscii( p, n );
p += n;
if ('E' != *p)
buf.append( (sal_Unicode)'.' );
}
#if OSL_DEBUG_LEVEL > 1
OUString ret( buf.makeStringAndClear() );
OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) );
fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() );
return ret;
#else
return buf.makeStringAndClear();
#endif
}
//==================================================================================================
class RTTI
{
typedef boost::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map;
Mutex m_mutex;
t_rtti_map m_rttis;
t_rtti_map m_generatedRttis;
void * m_hApp;
public:
RTTI() SAL_THROW( () );
~RTTI() SAL_THROW( () );
type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () );
};
//__________________________________________________________________________________________________
RTTI::RTTI() SAL_THROW( () )
: m_hApp( dlopen( 0, RTLD_LAZY ) )
{
}
//__________________________________________________________________________________________________
RTTI::~RTTI() SAL_THROW( () )
{
dlclose( m_hApp );
}
//__________________________________________________________________________________________________
type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () )
{
type_info * rtti;
OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName;
MutexGuard guard( m_mutex );
t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) );
if (iFind == m_rttis.end())
{
// RTTI symbol
OStringBuffer buf( 64 );
buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") );
sal_Int32 index = 0;
do
{
OUString token( unoName.getToken( 0, '.', index ) );
buf.append( token.getLength() );
OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) );
buf.append( c_token );
}
while (index >= 0);
buf.append( 'E' );
OString symName( buf.makeStringAndClear() );
rtti = (type_info *)dlsym( m_hApp, symName.getStr() );
if (rtti)
{
pair< t_rtti_map::iterator, bool > insertion(
m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" );
}
else
{
// try to lookup the symbol in the generated rtti map
t_rtti_map::const_iterator iFind2( m_generatedRttis.find( unoName ) );
if (iFind2 == m_generatedRttis.end())
{
// we must generate it !
// symbol and rtti-name is nearly identical,
// the symbol is prefixed with _ZTI
char const * rttiName = symName.getStr() +4;
#if OSL_DEBUG_LEVEL > 1
fprintf( stderr,"generated rtti for %s\n", rttiName );
#endif
if (pTypeDescr->pBaseTypeDescription)
{
// ensure availability of base
type_info * base_rtti = getRTTI(
(typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription );
rtti = new __si_class_type_info(
strdup( rttiName ), (__class_type_info *)base_rtti );
}
else
{
// this class has no base class
rtti = new __class_type_info( strdup( rttiName ) );
}
pair< t_rtti_map::iterator, bool > insertion(
m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" );
}
else // taking already generated rtti
{
rtti = iFind2->second;
}
}
}
else
{
rtti = iFind->second;
}
return rtti;
}
//--------------------------------------------------------------------------------------------------
static void deleteException( void * pExc )
{
__cxa_exception const * header = ((__cxa_exception const *)pExc - 1);
typelib_TypeDescription * pTD = 0;
OUString unoName( toUNOname( header->exceptionType->name() ) );
::typelib_typedescription_getByName( &pTD, unoName.pData );
OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" );
if (pTD)
{
::uno_destructData( pExc, pTD, cpp_release );
::typelib_typedescription_release( pTD );
}
}
//==================================================================================================
void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
{
#if OSL_DEBUG_LEVEL > 1
OString cstr(
OUStringToOString(
*reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
RTL_TEXTENCODING_ASCII_US ) );
fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() );
#endif
void * pCppExc;
type_info * rtti;
{
// construct cpp exception object
typelib_TypeDescription * pTypeDescr = 0;
TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType );
OSL_ASSERT( pTypeDescr );
if (! pTypeDescr)
{
throw RuntimeException(
OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) +
*reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
Reference< XInterface >() );
}
pCppExc = __cxa_allocate_exception( pTypeDescr->nSize );
::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );
// destruct uno exception
::uno_any_destruct( pUnoExc, 0 );
// avoiding locked counts
static RTTI * s_rtti = 0;
if (! s_rtti)
{
MutexGuard guard( Mutex::getGlobalMutex() );
if (! s_rtti)
{
#ifdef LEAK_STATIC_DATA
s_rtti = new RTTI();
#else
static RTTI rtti_data;
s_rtti = &rtti_data;
#endif
}
}
rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr );
TYPELIB_DANGER_RELEASE( pTypeDescr );
OSL_ENSURE( rtti, "### no rtti for throwing exception!" );
if (! rtti)
{
throw RuntimeException(
OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) +
*reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
Reference< XInterface >() );
}
}
__cxa_throw( pCppExc, rtti, deleteException );
}
//==================================================================================================
void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno )
{
if (! header)
{
RuntimeException aRE(
OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ),
Reference< XInterface >() );
Type const & rType = ::getCppuType( &aRE );
uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
#if OSL_DEBUG_LEVEL > 0
OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) );
OSL_FAIL( cstr.getStr() );
#endif
return;
}
typelib_TypeDescription * pExcTypeDescr = 0;
OUString unoName( toUNOname( header->exceptionType->name() ) );
#if OSL_DEBUG_LEVEL > 1
OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) );
fprintf( stderr, "> c++ exception occurred: %s\n", cstr_unoName.getStr() );
#endif
typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData );
if (0 == pExcTypeDescr)
{
RuntimeException aRE(
OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName,
Reference< XInterface >() );
Type const & rType = ::getCppuType( &aRE );
uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
#if OSL_DEBUG_LEVEL > 0
OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) );
OSL_FAIL( cstr.getStr() );
#endif
}
else
{
// construct uno exception any
uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno );
typelib_typedescription_release( pExcTypeDescr );
}
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#!/usr/bin/perl -w
# Version: MPL 1.1 / GPLv3+ / LGPLv3+
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License or as specified alternatively below. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Initial Developer of the Original Code is
# Tor Lillqvist <tml@iki.fi>
# Portions created by the Initial Developer are Copyright (C) 2011 the
# Initial Developer. All Rights Reserved.
#
# For minor contributions see the git repository.
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
# instead of those above.
my $nFunIndexes = 5;
my $nVtableOffsets = 1;
sub gen_arm ($$)
{
my ($funIndex, $vtableOffset) = @_;
printf ("codeSnippet%08x%d:\n", $funIndex, $vtableOffset);
printf ("\tmov ip, pc\n");
printf ("\tldr pc, [pc, #4]\n");
printf ("\t.long %#08x\n", $funIndex);
printf ("\t.long %d\n", $vtableOffset);
printf ("\t.long _privateSnippetExecutor\n");
}
sub gen_x86 ($$$)
{
my ($funIndex, $vtableOffset, $executor) = @_;
printf ("codeSnippet%08x%d%s:\n", $funIndex, $vtableOffset, $executor);
printf ("\tmovl %#08x, %%eax\n", $funIndex);
printf ("\tmovl \$%d, %%edx\n", $vtableOffset);
printf ("\tjmp _privateSnippetExecutor%s\n", $executor);
}
printf ("\t.text\n");
printf ("#ifdef __arm\n");
printf ("\t.align 4\n");
foreach my $funIndex (0 .. $nFunIndexes-1)
{
foreach my $vtableOffset (0 .. $nVtableOffsets-1)
{
gen_arm ($funIndex, $vtableOffset);
gen_arm ($funIndex|0x80000000, $vtableOffset);
}
}
printf ("#else\n");
foreach my $funIndex (0 .. $nFunIndexes-1)
{
foreach my $vtableOffset (0 .. $nVtableOffsets-1)
{
foreach my $executor ('General', 'Void', 'Hyper', 'Float', 'Double', 'Class')
{
gen_x86 ($funIndex, $vtableOffset, $executor);
gen_x86 ($funIndex|0x80000000, $vtableOffset, $executor);
}
}
}
printf ("#endif\n");
printf ("\t.globl _nFunIndexes\n");
printf ("_nFunIndexes:\n");
printf ("\t.long %d\n", $nFunIndexes);
printf ("\t.globl _nVtableOffsets\n");
printf ("_nVtableOffsets:\n");
printf ("\t.long %d\n", $nVtableOffsets);
printf ("\t.globl _codeSnippets\n");
printf ("_codeSnippets:\n");
foreach my $funIndex (0 .. $nFunIndexes-1)
{
foreach my $vtableOffset (0 .. $nVtableOffsets-1)
{
printf ("#ifdef __arm\n");
printf ("\t.long codeSnippet%08x%d\n", $funIndex, $vtableOffset);
printf ("\t.long codeSnippet%08x%d\n", $funIndex|0x80000000, $vtableOffset);
printf ("#else\n");
foreach my $executor ('General', 'Void', 'Hyper', 'Float', 'Double', 'Class')
{
printf ("\t.long codeSnippet%08x%d%s\n", $funIndex, $vtableOffset, $executor);
printf ("\t.long codeSnippet%08x%d%s\n", $funIndex|0x80000000, $vtableOffset, $executor);
}
printf ("#endif\n");
}
}
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
#ifdef __arm
@ ARM support code for LibreOffice C++/UNO bridging
@
@ Written by Peter Naulls <peter@chocky.org>
@ Modified by Caolan McNamara <caolanm@redhat.com>
@ Fixed by Michael Casadevall <mcasadevall@kubuntu.org>
@ Modified for iOS by Tor Lillqvist <tml@iki.fi>
.file "helper.S"
.text
.align 4
.globl privateSnippetExecutor
privateSnippetExecutor:
stmfd sp!, {r0-r3} @ follow other parameters on stack
mov r0, ip @ r0 points to functionoffset/vtable
mov r1, sp @ r1 points to this and params
@ (see cpp2uno.cxx:codeSnippet())
stmfd sp!, {r4,lr} @ save return address
@ (r4 pushed to preserve stack alignment)
bl cpp_vtable_call
add sp, sp, #4 @ no need to restore r4 (we didn't touch it)
ldr pc, [sp], #20 @ return, discarding function arguments
#else
.text
.align 1, 0x90
.globl _privateSnippetExecutorGeneral
_privateSnippetExecutorGeneral:
LFBg:
movl %esp,%ecx
pushl %ebp # proper stack frame needed for exception handling
LCFIg0:
movl %esp,%ebp
LCFIg1:
subl $0x8,%esp # padding + 32bit returnValue
pushl %esp # 32bit &returnValue
pushl %ecx # 32bit pCallStack
pushl %edx # 32bit nVtableOffset
pushl %eax # 32bit nFunctionIndex
call L_cpp_vtable_call$stub
movl 16(%esp),%eax # 32bit returnValue
leave
ret
LFEg:
.long .-_privateSnippetExecutorGeneral
.align 1, 0x90
.globl _privateSnippetExecutorVoid
_privateSnippetExecutorVoid:
LFBv:
movl %esp,%ecx
pushl %ebp # proper stack frame needed for exception handling
LCFIv0:
movl %esp,%ebp
LCFIv1:
sub $8,%esp # padding
pushl $0 # 32bit null pointer (returnValue not used)
pushl %ecx # 32bit pCallStack
pushl %edx # 32bit nVtableOffset
pushl %eax # 32bit nFunctionIndex
call L_cpp_vtable_call$stub
leave
ret
LFEv:
.long .-_privateSnippetExecutorVoid
.align 1, 0x90
.globl _privateSnippetExecutorHyper
_privateSnippetExecutorHyper:
LFBh:
movl %esp,%ecx
pushl %ebp # proper stack frame needed for exception handling
LCFIh0:
movl %esp,%ebp
LCFIh1:
subl $0x8,%esp # 64bit returnValue
pushl %esp # 32bit &returnValue
pushl %ecx # 32bit pCallStack
pushl %edx # 32bit nVtableOffset
pushl %eax # 32bit nFunctionIndex
call L_cpp_vtable_call$stub
movl 16(%esp),%eax # 64bit returnValue, lower half
movl 20(%esp),%edx # 64bit returnValue, upper half
leave
ret
LFEh:
.long .-_privateSnippetExecutorHyper
.align 1, 0x90
.globl _privateSnippetExecutorFloat
_privateSnippetExecutorFloat:
LFBf:
movl %esp,%ecx
pushl %ebp # proper stack frame needed for exception handling
LCFIf0:
movl %esp,%ebp
LCFIf1:
subl $0x8,%esp # padding + 32bit returnValue
pushl %esp # 32bit &returnValue
pushl %ecx # 32bit pCallStack
pushl %edx # 32bit nVtableOffset
pushl %eax # 32bit nFunctionIndex
call L_cpp_vtable_call$stub
flds 16(%esp) # 32bit returnValue
leave
ret
LFEf:
.long .-_privateSnippetExecutorFloat
.align 1, 0x90
.globl _privateSnippetExecutorDouble
_privateSnippetExecutorDouble:
LFBd:
movl %esp,%ecx
pushl %ebp # proper stack frame needed for exception handling
LCFId0:
movl %esp,%ebp
LCFId1:
subl $0x8,%esp # 64bit returnValue
pushl %esp # 32bit &returnValue
pushl %ecx # 32bit pCallStack
pushl %edx # 32bit nVtableOffset
pushl %eax # 32bit nFunctionIndex
call L_cpp_vtable_call$stub
fldl 16(%esp) # 64bit returnValue
leave
ret
LFEd:
.long .-_privateSnippetExecutorDouble
.align 1, 0x90
.globl _privateSnippetExecutorClass
_privateSnippetExecutorClass:
LFBc:
movl %esp,%ecx
pushl %ebp # proper stack frame needed for exception handling
LCFIc0:
movl %esp,%ebp
LCFIc1:
subl $0x8,%esp # padding + 32bit returnValue
pushl %esp # 32bit &returnValue
pushl %ecx # 32bit pCallStack
pushl %edx # 32bit nVtableOffset
pushl %eax # 32bit nFunctionIndex
call L_cpp_vtable_call$stub
movl 16(%esp),%eax # 32bit returnValue
leave
ret $4
LFEc:
.long .-_privateSnippetExecutorClass
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
.set L$set$frame1,LECIE1-LSCIE1
.long L$set$frame1 # length
LSCIE1:
.long 0 # CIE_ID
.byte 1 # version
.ascii "zPR\0" # augmentation
.byte 1 # code_alignment_factor (.uleb128 1)
.byte 0x7c # data_alignment_factor (.sleb128 -4)
.byte 8 # return_address_register
.byte 0x6 # augmentation size 7:
.byte 0x9b # ???
.long L___gxx_personality_v0$non_lazy_ptr-.
.byte 0x10
# initial_instructions:
.byte 0x0C # DW_CFA_def_cfa %esp, 4
.byte 5
.byte 4
.byte 0x88 # DW_CFA_offset ret, 1
.byte 1
.align 2
LECIE1:
.globl _privateSnippetExecutorGeneral.eh
_privateSnippetExecutorGeneral.eh:
LSFDEg:
.set L$set$g1,LEFDEg-LASFDEg
.long L$set$g1 # length
LASFDEg:
.long LASFDEg-EH_frame1 # CIE_pointer
.long LFBg-. # initial_location
.long LFEg-LFBg # address_range
.byte 0 # augmentation size 0
# instructions:
.byte 0x04 # DW_CFA_advance_loc4
.long LCFIg0-LFBg
.byte 0x0E # DW_CFA_def_cfa_offset 8
.byte 8
.byte 0x84 # DW_CFA_offset %ebp, 2
.byte 2
.byte 0x04 # DW_CFA_advance_loc4
.long LCFIg1-LCFIg0
.byte 0x0D # DW_CFA_def_cfa_register %ebp
.byte 4
.align 2
LEFDEg:
.globl _privateSnippetExecutorVoid.eh
_privateSnippetExecutorVoid.eh:
LSFDEv:
.set L$set$v1,LEFDEv-LASFDEv
.long L$set$v1 # length
LASFDEv:
.long LASFDEv-EH_frame1 # CIE_pointer
.long LFBv-. # initial_location
.long LFEv-LFBv # address_range
.byte 0 # augmentation size 0
# instructions:
.byte 0x04 # DW_CFA_advance_loc4
.long LCFIv0-LFBv
.byte 0x0E # DW_CFA_def_cfa_offset 8
.byte 8
.byte 0x84 # DW_CFA_offset %ebp, 2
.byte 2
.byte 0x04 # DW_CFA_advance_loc4
.long LCFIv1-LCFIv0
.byte 0x0D # DW_CFA_def_cfa_register %ebp
.byte 4
.align 2
LEFDEv:
.globl _privateSnippetExecutorHyper.eh
_privateSnippetExecutorHyper.eh:
LSFDEh:
.set L$set$h1,LEFDEh-LASFDEh
.long L$set$h1 # length
LASFDEh:
.long LASFDEh-EH_frame1 # CIE_pointer
.long LFBh-. # initial_location
.long LFEh-LFBh # address_range
.byte 0 # augmentation size 0
# instructions:
.byte 0x04 # DW_CFA_advance_loc4
.long LCFIh0-LFBh
.byte 0x0E # DW_CFA_def_cfa_offset 8
.byte 8
.byte 0x84 # DW_CFA_offset %ebp, 2
.byte 2
.byte 0x04 # DW_CFA_advance_loc4
.long LCFIh1-LCFIh0
.byte 0x0D # DW_CFA_def_cfa_register %ebp
.byte 4
.align 2
LEFDEh:
.globl _privateSnippetExecutorFloat.eh
_privateSnippetExecutorFloat.eh:
LSFDEf:
.set L$set$f1,LEFDEf-LASFDEf
.long L$set$f1 # length
LASFDEf:
.long LASFDEf-EH_frame1 # CIE_pointer
.long LFBf-. # initial_location
.long LFEf-LFBf # address_range
.byte 0 # augmentation size 0
# instructions:
.byte 0x04 # DW_CFA_advance_loc4
.long LCFIf0-LFBf
.byte 0x0E # DW_CFA_def_cfa_offset 8
.byte 8
.byte 0x84 # DW_CFA_offset %ebp, 2
.byte 2
.byte 0x04 # DW_CFA_advance_loc4
.long LCFIf1-LCFIf0
.byte 0x0D # DW_CFA_def_cfa_register %ebp
.byte 4
.align 2
LEFDEf:
.globl _privateSnippetExecutorDouble.eh
_privateSnippetExecutorDouble.eh:
LSFDEd:
.set L$set$d1,LEFDEd-LASFDEd
.long L$set$d1 # length
LASFDEd:
.long LASFDEd-EH_frame1 # CIE_pointer
.long LFBd-. # initial_location
.long LFEd-LFBd # address_range
.byte 0 # augmentation size 0
# instructions:
.byte 0x04 # DW_CFA_advance_loc4
.long LCFId0-LFBd
.byte 0x0E # DW_CFA_def_cfa_offset 8
.byte 8
.byte 0x84 # DW_CFA_offset %ebp, 2
.byte 2
.byte 0x04 # DW_CFA_advance_loc4
.long LCFId1-LCFId0
.byte 0x0D # DW_CFA_def_cfa_register %ebp
.byte 4
.align 2
LEFDEd:
.globl _privateSnippetExecutorClass.eh
_privateSnippetExecutorClass.eh:
LSFDEc:
.set L$set$c1,LEFDEc-LASFDEc
.long L$set$c1 # length
LASFDEc:
.long LASFDEc-EH_frame1 # CIE_pointer
.long LFBc-. # initial_location
.long LFEc-LFBc # address_range
.byte 0 # augmentation size 0
# instructions:
.byte 0x04 # DW_CFA_advance_loc4
.long LCFIc0-LFBc
.byte 0x0E # DW_CFA_def_cfa_offset 8
.byte 8
.byte 0x84 # DW_CFA_offset %ebp, 2
.byte 2
.byte 0x04 # DW_CFA_advance_loc4
.long LCFIc1-LCFIc0
.byte 0x0D # DW_CFA_def_cfa_register %ebp
.byte 4
.align 2
LEFDEc:
.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
L_cpp_vtable_call$stub:
.indirect_symbol _cpp_vtable_call
hlt ; hlt ; hlt ; hlt ; hlt
.section __IMPORT,__pointers,non_lazy_symbol_pointers
L___gxx_personality_v0$non_lazy_ptr:
.indirect_symbol ___gxx_personality_v0
.long 0
.constructor
.destructor
.align 1
#endif
#*************************************************************************
#
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# Copyright 2000, 2010 Oracle and/or its affiliates.
#
# OpenOffice.org - a multi-platform office productivity suite
#
# This file is part of OpenOffice.org.
#
# OpenOffice.org is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version 3
# only, as published by the Free Software Foundation.
#
# OpenOffice.org is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License version 3 for more details
# (a copy is included in the LICENSE file that accompanied this code).
#
# You should have received a copy of the GNU Lesser General Public License
# version 3 along with OpenOffice.org. If not, see
# <http://www.openoffice.org/license.html>
# for a copy of the LGPLv3 License.
#
#*************************************************************************
PRJ=..$/..$/..
PRJNAME=bridges
TARGET=gcc3_uno
LIBTARGET=no
ENABLE_EXCEPTIONS=TRUE
# --- Settings -----------------------------------------------------
.INCLUDE : settings.mk
# --- Files --------------------------------------------------------
.IF "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCIOSRgcc3"
.IF "$(cppu_no_leak)" == ""
CFLAGS += -DLEAK_STATIC_DATA
.ENDIF
CFLAGSNOOPT=-O0
SLOFILES= \
$(SLO)$/except.obj \
$(SLO)$/cpp2uno.obj \
$(SLO)$/uno2cpp.obj \
$(SLO)$/codesnippets.obj \
$(SLO)$/helper.obj
SHL1TARGET= $(TARGET)
SHL1DEF=$(MISC)$/$(SHL1TARGET).def
SHL1IMPLIB=i$(TARGET)
SHL1VERSIONMAP=..$/..$/bridge_exports.map
SHL1OBJS = $(SLOFILES)
SHL1LIBS = $(SLB)$/cpp_uno_shared.lib
SHL1RPATH = URELIB
SHL1STDLIBS= \
$(CPPULIB) \
$(SALLIB)
.ENDIF
# --- Targets ------------------------------------------------------
.INCLUDE : target.mk
$(SLO)$/%.obj: %.S
$(CC) -c -o $(SLO)$/$(@:b).o $<
touch $@
codesnippets.S: generate-snippets.pl
$(PERL) generate-snippets.pl >$@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
#include "uno/mapping.h"
#include <typeinfo>
#include <exception>
#include <cstddef>
namespace CPPU_CURRENT_NAMESPACE
{
bool isSimpleReturnType(typelib_TypeDescription * pTD, bool recursive = false);
void dummy_can_throw_anything( char const * );
// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h
struct _Unwind_Exception
{
unsigned exception_class __attribute__((__mode__(__DI__)));
void * exception_cleanup;
unsigned private_1 __attribute__((__mode__(__word__)));
unsigned private_2 __attribute__((__mode__(__word__)));
} __attribute__((__aligned__));
struct __cxa_exception
{
::std::type_info *exceptionType;
void (*exceptionDestructor)(void *);
::std::unexpected_handler unexpectedHandler;
::std::terminate_handler terminateHandler;
__cxa_exception *nextException;
int handlerCount;
int handlerSwitchValue;
const unsigned char *actionRecord;
const unsigned char *languageSpecificData;
void *catchTemp;
void *adjustedPtr;
_Unwind_Exception unwindHeader;
};
extern "C" void *__cxa_allocate_exception(
std::size_t thrown_size ) throw();
extern "C" void __cxa_throw (
void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn));
struct __cxa_eh_globals
{
__cxa_exception *caughtExceptions;
unsigned int uncaughtExceptions;
};
extern "C" __cxa_eh_globals *__cxa_get_globals () throw();
// -----
//==================================================================================================
void raiseException(
uno_Any * pUnoExc, uno_Mapping * pUno2Cpp );
//==================================================================================================
void fillUnoException(
__cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_bridges.hxx"
#include <stdio.h>
#include <com/sun/star/uno/genfunc.hxx>
#include "com/sun/star/uno/RuntimeException.hpp"
#include <uno/data.h>
#include "bridges/cpp_uno/shared/bridge.hxx"
#include "bridges/cpp_uno/shared/types.hxx"
#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
#include "bridges/cpp_uno/shared/vtables.hxx"
#include "share.hxx"
using namespace ::rtl;
using namespace ::com::sun::star::uno;
namespace
{
//==================================================================================================
// The call instruction within the asm section of callVirtualMethod may throw
// exceptions. So that the compiler handles this correctly, it is important
// that (a) callVirtualMethod might call dummy_can_throw_anything (although this
// never happens at runtime), which in turn can throw exceptions, and (b)
// callVirtualMethod is not inlined at its call site (so that any exceptions are
// caught which are thrown from the instruction calling callVirtualMethod):
void callVirtualMethod(
void * pAdjustedThisPtr,
sal_Int32 nVtableIndex,
void * pRegisterReturn,
typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn,
sal_Int32 * pStackLongs,
sal_Int32 nStackLongs ) __attribute__((noinline));
void callVirtualMethod(
void * pAdjustedThisPtr,
sal_Int32 nVtableIndex,
void * pRegisterReturn,
typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn,
sal_Int32 * pStackLongs,
sal_Int32 nStackLongs )
{
// parameter list is mixed list of * and values
// reference parameters are pointers
OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" );
OSL_ENSURE( (sizeof(void *) == 4) && (sizeof(sal_Int32) == 4), "### unexpected size of int!" );
OSL_ENSURE( nStackLongs && pStackLongs, "### no stack in callVirtualMethod !" );
// never called
if (! pAdjustedThisPtr) CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something
#ifdef __arm
#else
volatile long edx = 0, eax = 0; // for register returns
void * stackptr;
asm volatile (
"mov %%esp, %6\n\t"
"mov %0, %%eax\n\t"
"mov %%eax, %%edx\n\t"
// stack padding to keep stack aligned:
"shl $2, %%eax\n\t"
"neg %%eax\n\t"
"add %%esp, %%eax\n\t"
"and $0xf, %%eax\n\t"
"sub %%eax, %%esp\n\t"
// copy:
"mov %%edx, %%eax\n\t"
"dec %%edx\n\t"
"shl $2, %%edx\n\t"
"add %1, %%edx\n"
"Lcopy:\n\t"
"pushl 0(%%edx)\n\t"
"sub $4, %%edx\n\t"
"dec %%eax\n\t"
"jne Lcopy\n\t"
// do the actual call
"mov %2, %%edx\n\t"
"mov 0(%%edx), %%edx\n\t"
"mov %3, %%eax\n\t"
"shl $2, %%eax\n\t"
"add %%eax, %%edx\n\t"
"mov 0(%%edx), %%edx\n\t"
"call *%%edx\n\t"
// save return registers
"mov %%eax, %4\n\t"
"mov %%edx, %5\n\t"
// cleanup stack
"mov %6, %%esp\n\t"
:
: "m"(nStackLongs), "m"(pStackLongs), "m"(pAdjustedThisPtr),
"m"(nVtableIndex), "m"(eax), "m"(edx), "m"(stackptr)
: "eax", "edx" );
switch( pReturnTypeDescr->eTypeClass )
{
case typelib_TypeClass_VOID:
break;
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
((long*)pRegisterReturn)[1] = edx;
case typelib_TypeClass_LONG:
case typelib_TypeClass_UNSIGNED_LONG:
case typelib_TypeClass_CHAR:
case typelib_TypeClass_ENUM:
((long*)pRegisterReturn)[0] = eax;
break;
case typelib_TypeClass_SHORT:
case typelib_TypeClass_UNSIGNED_SHORT:
*(unsigned short*)pRegisterReturn = eax;
break;
case typelib_TypeClass_BOOLEAN:
case typelib_TypeClass_BYTE:
*(unsigned char*)pRegisterReturn = eax;
break;
case typelib_TypeClass_FLOAT:
asm ( "fstps %0" : : "m"(*(char *)pRegisterReturn) );
break;
case typelib_TypeClass_DOUBLE:
asm ( "fstpl %0\n\t" : : "m"(*(char *)pRegisterReturn) );
break;
default: {
sal_Int32 const nRetSize = pReturnTypeDescr->nSize;
if (bSimpleReturn && nRetSize <= 8 && nRetSize > 0) {
if (nRetSize > 4)
static_cast<long *>(pRegisterReturn)[1] = edx;
static_cast<long *>(pRegisterReturn)[0] = eax;
}
break;
}
}
#endif
}
//==================================================================================================
static void cpp_call(
bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
bridges::cpp_uno::shared::VtableSlot aVtableSlot,
typelib_TypeDescriptionReference * pReturnTypeRef,
sal_Int32 nParams, typelib_MethodParameter * pParams,
void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
{
// max space for: [complex ret ptr], values|ptr ...
char * pCppStack =
(char *)alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) );
char * pCppStackStart = pCppStack;
// 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)
{
bSimpleReturn = CPPU_CURRENT_NAMESPACE::isSimpleReturnType(
pReturnTypeDescr);
if (bSimpleReturn)
{
pCppReturn = pUnoReturn; // direct way for simple types
}
else
{
pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(
pReturnTypeDescr )
? alloca( pReturnTypeDescr->nSize )
: pUnoReturn); // direct way
// complex return via ptr
*(void **)pCppStack = pCppReturn;
pCppStack += sizeof(void *);
}
}
// push this
void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
+ aVtableSlot.offset;
*(void**)pCppStack = pAdjustedThisPtr;
pCppStack += sizeof( void* );
// stack space
OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
// args
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;
for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
{
const typelib_MethodParameter & rParam = pParams[nPos];
typelib_TypeDescription * pParamTypeDescr = 0;
TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
if (!rParam.bOut
&& bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
{
uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr,
pThis->getBridge()->getUno2Cpp() );
switch (pParamTypeDescr->eTypeClass)
{
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
case typelib_TypeClass_DOUBLE:
pCppStack += sizeof(sal_Int32); // extra long
default:
break;
}
// no longer needed
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
else // ptr to complex value | ref
{
if (! rParam.bIn) // is pure out
{
// cpp out is constructed mem, uno out is not!
uno_constructData(
*(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
pParamTypeDescr );
pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
// will be released at reconversion
ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
}
// is in/inout
else if (bridges::cpp_uno::shared::relatesToInterfaceType(
pParamTypeDescr ))
{
uno_copyAndConvertData(
*(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
pUnoArgs[nPos], pParamTypeDescr,
pThis->getBridge()->getUno2Cpp() );
pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
// will be released at reconversion
ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
}
else // direct way
{
*(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos];
// no longer needed
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
}
pCppStack += sizeof(sal_Int32); // standard parameter length
}
try
{
OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic)" );
callVirtualMethod(
pAdjustedThisPtr, aVtableSlot.index,
pCppReturn, pReturnTypeDescr, bSimpleReturn,
(sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) );
// NO exception occurred...
*ppUnoExc = 0;
// reconvert temporary params
for ( ; nTempIndizes--; )
{
sal_Int32 nIndex = pTempIndizes[nTempIndizes];
typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
if (pParams[nIndex].bIn)
{
if (pParams[nIndex].bOut) // inout
{
uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
pThis->getBridge()->getCpp2Uno() );
}
}
else // pure out
{
uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
pThis->getBridge()->getCpp2Uno() );
}
// destroy temp cpp param => cpp: every param was constructed
uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
// return value
if (pCppReturn && pUnoReturn != pCppReturn)
{
uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
pThis->getBridge()->getCpp2Uno() );
uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
}
}
catch (...)
{
#if OSL_DEBUG_LEVEL > 1
fprintf( stderr, "caught C++ exception\n" );
#endif
// fill uno exception
fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
// temporary params
for ( ; nTempIndizes--; )
{
sal_Int32 nIndex = pTempIndizes[nTempIndizes];
// destroy temp cpp param => cpp: every param was constructed
uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
}
// return type
if (pReturnTypeDescr)
TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
}
}
}
namespace CPPU_CURRENT_NAMESPACE {
bool isSimpleReturnType(typelib_TypeDescription * pTD, bool recursive)
{
if (bridges::cpp_uno::shared::isSimpleType( pTD ))
return true;
// Only structs of exactly 1, 2, 4, or 8 bytes are returned through
// registers, see <http://developer.apple.com/documentation/DeveloperTools/
// Conceptual/LowLevelABI/Articles/IA32.html>:
if (pTD->eTypeClass == typelib_TypeClass_STRUCT &&
(recursive || pTD->nSize <= 2 || pTD->nSize == 4 || pTD->nSize == 8))
{
typelib_CompoundTypeDescription *const pCompTD =
(typelib_CompoundTypeDescription *) pTD;
for ( sal_Int32 pos = pCompTD->nMembers; pos--; ) {
typelib_TypeDescription * pMemberTD = 0;
TYPELIB_DANGER_GET( &pMemberTD, pCompTD->ppTypeRefs[pos] );
bool const b = isSimpleReturnType(pMemberTD, true);
TYPELIB_DANGER_RELEASE( pMemberTD );
if (! b)
return false;
}
return true;
}
return false;
}
}
//==================================================================================================
namespace bridges { namespace cpp_uno { namespace shared {
void unoInterfaceProxyDispatch(
uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
void * pReturn, void * pArgs[], uno_Any ** ppException )
{
// is my surrogate
bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
= static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
switch (pMemberDescr->eTypeClass)
{
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
{
VtableSlot aVtableSlot(
getVtableSlot(
reinterpret_cast<
typelib_InterfaceAttributeTypeDescription const * >(
pMemberDescr)));
if (pReturn)
{
// dependent dispatch
cpp_call(
pThis, aVtableSlot,
((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
0, 0, // no params
pReturn, pArgs, ppException );
}
else
{
// is SET
typelib_MethodParameter aParam;
aParam.pTypeRef =
((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
aParam.bIn = sal_True;
aParam.bOut = sal_False;
typelib_TypeDescriptionReference * pReturnTypeRef = 0;
OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
typelib_typedescriptionreference_new(
&pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
// dependent dispatch
aVtableSlot.index += 1; // get, then set method
cpp_call(
pThis, aVtableSlot,
pReturnTypeRef,
1, &aParam,
pReturn, pArgs, ppException );
typelib_typedescriptionreference_release( pReturnTypeRef );
}
break;
}
case typelib_TypeClass_INTERFACE_METHOD:
{
VtableSlot aVtableSlot(
getVtableSlot(
reinterpret_cast<
typelib_InterfaceMethodTypeDescription const * >(
pMemberDescr)));
switch (aVtableSlot.index)
{
// standard calls
case 1: // acquire uno interface
(*pUnoI->acquire)( pUnoI );
*ppException = 0;
break;
case 2: // release uno interface
(*pUnoI->release)( pUnoI );
*ppException = 0;
break;
case 0: // queryInterface() opt
{
typelib_TypeDescription * pTD = 0;
TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
if (pTD)
{
uno_Interface * pInterface = 0;
(*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
pThis->pBridge->getUnoEnv(),
(void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
if (pInterface)
{
::uno_any_construct(
reinterpret_cast< uno_Any * >( pReturn ),
&pInterface, pTD, 0 );
(*pInterface->release)( pInterface );
TYPELIB_DANGER_RELEASE( pTD );
*ppException = 0;
break;
}
TYPELIB_DANGER_RELEASE( pTD );
}
} // else perform queryInterface()
default:
// dependent dispatch
cpp_call(
pThis, aVtableSlot,
((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
pReturn, pArgs, ppException );
}
break;
}
default:
{
::com::sun::star::uno::RuntimeException aExc(
OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
Type const & rExcType = ::getCppuType( &aExc );
// binary identical null reference
::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
}
}
}
} } }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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