[Libreoffice-commits] .: 3 commits - bridges/prj bridges/source i18npool/qa

Tor Lillqvist tml at kemper.freedesktop.org
Sat Aug 13 14:53:04 PDT 2011


 bridges/prj/build.lst                                    |    1 
 bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno.cxx          |  543 +++++++++++++++
 bridges/source/cpp_uno/gcc3_ios_arm/except.cxx           |  331 +++++++++
 bridges/source/cpp_uno/gcc3_ios_arm/generate-snippets.pl |  107 ++
 bridges/source/cpp_uno/gcc3_ios_arm/helper.S             |  353 +++++++++
 bridges/source/cpp_uno/gcc3_ios_arm/makefile.mk          |   81 ++
 bridges/source/cpp_uno/gcc3_ios_arm/share.hxx            |   95 ++
 bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp.cxx          |  500 +++++++++++++
 bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx        |    3 
 i18npool/qa/cppunit/i18npool_cppunittester_all.cxx       |    2 
 10 files changed, 2016 insertions(+)

New commits:
commit b7254fcd897e9359ac44d04c9eca91e2b6f403e3
Author: Tor Lillqvist <tml at iki.fi>
Date:   Sun Aug 14 00:47:48 2011 +0300

    Try to make i18npool_cppunittester_all work

diff --git a/i18npool/qa/cppunit/i18npool_cppunittester_all.cxx b/i18npool/qa/cppunit/i18npool_cppunittester_all.cxx
index 04cb36a..1434dc9 100644
--- a/i18npool/qa/cppunit/i18npool_cppunittester_all.cxx
+++ b/i18npool/qa/cppunit/i18npool_cppunittester_all.cxx
@@ -119,6 +119,8 @@ extern "C" CppUnitTestPlugIn
 
 
 SAL_IMPLEMENT_MAIN() {
+    putenv("UNO_SERVICES=services.rdb");
+    putenv("UNO_TYPES=types.rdb udkapi.rdb");
     TestPlugInSignature plugs[] = {
         cppunitTest_i18npool_breakiterator,
         NULL
commit 9540af1ece646bd7b2ff31dad91e629a984d8904
Author: Tor Lillqvist <tml at iki.fi>
Date:   Sun Aug 14 00:32:43 2011 +0300

    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.

diff --git a/bridges/prj/build.lst b/bridges/prj/build.lst
index 9c7b2f3..d3d5f6d 100644
--- a/bridges/prj/build.lst
+++ b/bridges/prj/build.lst
@@ -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_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_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\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
diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno.cxx
new file mode 100644
index 0000000..110013b
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno.cxx
@@ -0,0 +1,543 @@
+/* -*- 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: */
diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/except.cxx b/bridges/source/cpp_uno/gcc3_ios_arm/except.cxx
new file mode 100644
index 0000000..a14bc8b
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_ios_arm/except.cxx
@@ -0,0 +1,331 @@
+/* -*- 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: */
diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/generate-snippets.pl b/bridges/source/cpp_uno/gcc3_ios_arm/generate-snippets.pl
new file mode 100755
index 0000000..4fe9f2f
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_ios_arm/generate-snippets.pl
@@ -0,0 +1,107 @@
+#!/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 at 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");
+    }
+}
diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/helper.S b/bridges/source/cpp_uno/gcc3_ios_arm/helper.S
new file mode 100644
index 0000000..0bd718b
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_ios_arm/helper.S
@@ -0,0 +1,353 @@
+/*************************************************************************
+ *
+ * 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 at chocky.org>
+@ Modified by Caolan McNamara <caolanm at redhat.com>
+@ Fixed by Michael Casadevall <mcasadevall at kubuntu.org>
+@ Modified for iOS by Tor Lillqvist <tml at 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
diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/makefile.mk b/bridges/source/cpp_uno/gcc3_ios_arm/makefile.mk
new file mode 100644
index 0000000..55e6ca7
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_ios_arm/makefile.mk
@@ -0,0 +1,81 @@
+#*************************************************************************
+#
+# 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 >$@
+
diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/share.hxx b/bridges/source/cpp_uno/gcc3_ios_arm/share.hxx
new file mode 100644
index 0000000..8b105c0
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_ios_arm/share.hxx
@@ -0,0 +1,95 @@
+/* -*- 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: */
diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp.cxx
new file mode 100644
index 0000000..9793f28
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp.cxx
@@ -0,0 +1,500 @@
+/* -*- 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: */
commit 2ba07916ffe8211410bc2d2e0c1a4c9ac77f601e
Author: Tor Lillqvist <tml at iki.fi>
Date:   Sat Aug 13 22:46:45 2011 +0300

    Add some comments

diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx
index 937f387..737824c 100644
--- a/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx
@@ -450,7 +450,10 @@ namespace
 
         unsigned long * p = (unsigned long *)code;
 
+        // ARM (not thumb) mode instructions
+        // mov ip, pc
         *p++ = 0xE1A0C00F;
+        // ldr pc, [pc, #4]
         *p++ = 0xE59FF004;
         *p++ = (unsigned long)functionIndex;
         *p++ = (unsigned long)vtableOffset;


More information about the Libreoffice-commits mailing list