$OpenBSD: patch-bridges_source_cpp_uno_gcc3_linux_intel_cpp2uno_cxx,v 1.1 2010/12/10 23:25:35 robert Exp $
--- bridges/source/cpp_uno/gcc3_linux_intel/cpp2uno.cxx.orig.port	Fri Dec 10 11:00:36 2010
+++ bridges/source/cpp_uno/gcc3_linux_intel/cpp2uno.cxx	Fri Dec 10 11:00:39 2010
@@ -1,3 +1,4 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /*************************************************************************
  *
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -47,179 +48,179 @@ 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 )
+    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);
+    // 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)
-	{
-		if (bridges::cpp_uno::shared::isSimpleType( 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(
+    // 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)
+    {
+        if (x86::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* );
+                          ? 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 );
+    // 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
+        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
+        {
+            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
                 break;
             default:
                 break;
-			}
-			// no longer needed
-			TYPELIB_DANGER_RELEASE( pParamTypeDescr );
-		}
-		else // ptr to complex value | ref
-		{
-			pCppArgs[nPos] = *(void **)pCppStack;
+            }
+            // 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(
+            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;
+            {
+                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)(
+    // invoke uno dispatch call
+    (*pThis->getUnoI()->pDispatcher)(
         pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
-	
-	// in case an exception occured...
-	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(
+    
+    // in case an exception occured...
+    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 occured...
-	{
-		// 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 );
-			}
-			// complex return ptr is set to eax
-			*static_cast< void ** >(pReturnValue) = pCppReturn;
-		}
-		if (pReturnTypeDescr)
-		{
-			TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
-		}
-	}
+    }
+    else // else no exception occured...
+    {
+        // 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 );
+            }
+            // complex return ptr is set to eax
+            *static_cast< void ** >(pReturnValue) = pCppReturn;
+        }
+        if (pReturnTypeDescr)
+        {
+            TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
+        }
+    }
 }
 
 
@@ -228,93 +229,93 @@ 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
+    OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
+    
+    // pCallStack: ret adr, [ret *], this, params
     void * pThis;
-	if( nFunctionIndex & 0x80000000 )
-	{
-		nFunctionIndex &= 0x7fffffff;
+    if( nFunctionIndex & 0x80000000 )
+    {
+        nFunctionIndex &= 0x7fffffff;
         pThis = pCallStack[2];
-	}
-	else
+    }
+    else
     {
         pThis = pCallStack[1];
     }
     pThis = static_cast< char * >(pThis) - nVtableOffset;
-	bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
+    bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
         = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
             pThis);
     
-	typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
-	
-	OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
-	if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
-	{
-		throw RuntimeException(
+    typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
+    
+    OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
+    if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
+    {
+        throw RuntimeException(
             rtl::OUString::createFromAscii("illegal vtable index!"),
             (XInterface *)pThis );
-	}
-	
-	// determine called method
-	sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
-	OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
+    }
+    
+    // determine called method
+    sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
+    OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
 
-	TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
+    TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
     
-	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)
-			{
+    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(
@@ -327,24 +328,24 @@ extern "C" void cpp_vtable_call(
                 }
                 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(
+        } // 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::createFromAscii("no member description found!"),
             (XInterface *)pThis );
-	}
-	}
+    }
+    }
 }
 
 //==================================================================================================
@@ -358,15 +359,39 @@ extern "C" typedef void (*PrivateSnippetExecutor)();
 
 int const codeSnippetSize = 16;
 
+#if defined (FREEBSD) || defined(NETBSD) || defined(OPENBSD) || defined(MACOSX)
+namespace
+{
+    PrivateSnippetExecutor returnsInRegister(typelib_TypeDescriptionReference * pReturnTypeRef)
+    {
+        //These archs apparently are returning small structs in registers, while Linux
+        //doesn't
+        PrivateSnippetExecutor exec=NULL;
+
+        typelib_TypeDescription * pReturnTypeDescr = 0;
+        TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
+        const bool bSimpleReturnStruct = x86::isSimpleReturnType(pReturnTypeDescr);
+        const sal_Int32 nRetSize = pReturnTypeDescr->nSize;
+        TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
+        if (bSimpleReturnStruct)
+        {
+            exec = privateSnippetExecutorGeneral; // fills eax
+            if (nRetSize > 4)
+                exec = privateSnippetExecutorHyper; // fills eax/edx
+        }
+        return exec;
+    }
+}
+#endif
+
 unsigned char * codeSnippet(
     unsigned char * code, sal_PtrDiff writetoexecdiff, sal_Int32 functionIndex, sal_Int32 vtableOffset,
-    typelib_TypeClass returnTypeClass)
+    typelib_TypeDescriptionReference * pReturnTypeRef)
 {
-    if (!bridges::cpp_uno::shared::isSimpleType(returnTypeClass)) {
-        functionIndex |= 0x80000000;
-    }
     PrivateSnippetExecutor exec;
-    switch (returnTypeClass) {
+    typelib_TypeClass eReturnClass = pReturnTypeRef ? pReturnTypeRef->eTypeClass : typelib_TypeClass_VOID;
+    switch (eReturnClass)
+    {
     case typelib_TypeClass_VOID:
         exec = privateSnippetExecutorVoid;
         break;
@@ -380,13 +405,24 @@ unsigned char * codeSnippet(
     case typelib_TypeClass_DOUBLE:
         exec = privateSnippetExecutorDouble;
         break;
+    case typelib_TypeClass_STRUCT:
+    case typelib_TypeClass_EXCEPTION:
+#if defined (FREEBSD) || defined(NETBSD) || defined(OPENBSD) || defined(MACOSX)
+        exec = returnsInRegister(pReturnTypeRef);
+        if (!exec)
+        {
+            exec = privateSnippetExecutorClass;
+            functionIndex |= 0x80000000;
+        }
+        break;
+#endif
     case typelib_TypeClass_STRING:
     case typelib_TypeClass_TYPE:
     case typelib_TypeClass_ANY:
     case typelib_TypeClass_SEQUENCE:
-    case typelib_TypeClass_STRUCT:
     case typelib_TypeClass_INTERFACE:
         exec = privateSnippetExecutorClass;
+        functionIndex |= 0x80000000;
         break;
     default:
         exec = privateSnippetExecutorGeneral;
@@ -454,7 +490,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactor
             code = codeSnippet(
                 code, writetoexecdiff, functionOffset++, vtableOffset,
                 reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >(
-                    member)->pAttributeTypeRef->eTypeClass);
+                    member)->pAttributeTypeRef);
             // Setter:
             if (!reinterpret_cast<
                 typelib_InterfaceAttributeTypeDescription * >(
@@ -463,7 +499,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactor
                 (s++)->fn = code + writetoexecdiff;
                 code = codeSnippet(
                     code, writetoexecdiff, functionOffset++, vtableOffset,
-                    typelib_TypeClass_VOID);
+                    NULL);
             }
             break;
 
@@ -472,7 +508,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactor
             code = codeSnippet(
                 code, writetoexecdiff, functionOffset++, vtableOffset,
                 reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(
-                    member)->pReturnTypeRef->eTypeClass);
+                    member)->pReturnTypeRef);
             break;
 
         default:
@@ -487,3 +523,5 @@ unsigned char * bridges::cpp_uno::shared::VtableFactor
 void bridges::cpp_uno::shared::VtableFactory::flushCode(
     unsigned char const *, unsigned char const *)
 {}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
