summaryrefslogtreecommitdiff
path: root/bridges
diff options
context:
space:
mode:
authorTor Lillqvist <tml@iki.fi>2012-09-26 22:51:03 +0300
committerTor Lillqvist <tml@iki.fi>2012-09-27 08:20:44 +0300
commitd83de4b1a93ba7ed7bc3243073be3de96a44bfa9 (patch)
treeef5bbc6a0d8155fcab8a6029f3cf45ebdbc86f9b /bridges
parent30d33b126f47021a99fb8ca63d6c6be29407e9cc (diff)
First attempt at C++/UNO bridge for 64-bit OS X
Basically, a 1:1 copy of the Linux x86-64 one. The Apple docs say that "The OS X x86-64 function calling conventions are the same as the function calling conventions described in System V Application Binary Interface AMD64 Architecture Processor Supplement," which should mean that it's the same as on Linux. Once this works, the very minor differences to the Linux one will be merged as ifdefs into the Linux one, and no separate source files will be needed. Change-Id: I1ff58f303a7ab7f59ec2ff7a9e24465e89151ec5
Diffstat (limited to 'bridges')
-rw-r--r--bridges/Library_gcc3_macosx_x86-64.mk72
-rw-r--r--bridges/Module_bridges.mk3
-rw-r--r--bridges/inc/bridges/cpp_uno/shared/vtablefactory.hxx3
-rw-r--r--bridges/source/cpp_uno/gcc3_macosx_x86-64/abi.cxx330
-rw-r--r--bridges/source/cpp_uno/gcc3_macosx_x86-64/abi.hxx70
-rw-r--r--bridges/source/cpp_uno/gcc3_macosx_x86-64/call.s79
-rw-r--r--bridges/source/cpp_uno/gcc3_macosx_x86-64/callvirtualmethod.cxx173
-rw-r--r--bridges/source/cpp_uno/gcc3_macosx_x86-64/callvirtualmethod.hxx50
-rw-r--r--bridges/source/cpp_uno/gcc3_macosx_x86-64/cpp2uno.cxx525
-rw-r--r--bridges/source/cpp_uno/gcc3_macosx_x86-64/except.cxx389
-rw-r--r--bridges/source/cpp_uno/gcc3_macosx_x86-64/share.hxx104
-rw-r--r--bridges/source/cpp_uno/gcc3_macosx_x86-64/uno2cpp.cxx459
12 files changed, 2256 insertions, 1 deletions
diff --git a/bridges/Library_gcc3_macosx_x86-64.mk b/bridges/Library_gcc3_macosx_x86-64.mk
new file mode 100644
index 000000000000..b7b69c474487
--- /dev/null
+++ b/bridges/Library_gcc3_macosx_x86-64.mk
@@ -0,0 +1,72 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+ifneq ($(strip $(bridges_SELECTED_BRIDGE)),)
+$(eval $(call gb_Output_error,cannot build bridge gcc3_linux_x86-64: bridge $(bridges_SELECTED_BRIDGE) already selected))
+endif
+bridges_SELECTED_BRIDGE := gcc3_macosx_x86-64
+
+$(eval $(call gb_Library_Library,gcc3_uno))
+
+$(eval $(call gb_Library_use_internal_comprehensive_api,gcc3_uno,\
+ udkapi \
+))
+
+$(eval $(call gb_Library_set_include,gcc3_uno,\
+ -I$(SRCDIR)/bridges/inc \
+ $$(INCLUDE) \
+))
+
+ifeq ($(HAVE_POSIX_FALLOCATE),YES)
+$(eval $(call gb_Library_add_defs,gcc3_uno,\
+ -DHAVE_POSIX_FALLOCATE \
+))
+endif
+
+# In case someone enabled the non-standard -fomit-frame-pointer which does not
+# work with the .cxx sources of this library.
+# In case the compiler supports AVX this code segfaults so specifically turn
+# it off.
+$(eval $(call gb_Library_add_cxxflags,gcc3_uno,\
+ -fno-omit-frame-pointer \
+ -fno-strict-aliasing \
+ $(if $(filter TRUE,$(HAVE_GCC_AVX)),\
+ -mno-avx \
+ ) \
+))
+
+$(eval $(call gb_Library_use_libraries,gcc3_uno,\
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_Library_add_asmobjects,gcc3_uno,\
+ bridges/source/cpp_uno/gcc3_macosx_x86-64/call \
+))
+
+$(eval $(call gb_Library_add_exception_objects,gcc3_uno,\
+ bridges/source/cpp_uno/gcc3_macosx_x86-64/abi \
+ bridges/source/cpp_uno/gcc3_macosx_x86-64/callvirtualmethod \
+ bridges/source/cpp_uno/gcc3_macosx_x86-64/cpp2uno \
+ bridges/source/cpp_uno/gcc3_macosx_x86-64/except \
+ bridges/source/cpp_uno/gcc3_macosx_x86-64/uno2cpp \
+ bridges/source/cpp_uno/shared/bridge \
+ bridges/source/cpp_uno/shared/component \
+ bridges/source/cpp_uno/shared/types \
+ bridges/source/cpp_uno/shared/unointerfaceproxy \
+ bridges/source/cpp_uno/shared/vtablefactory \
+ bridges/source/cpp_uno/shared/vtables \
+))
+
+$(eval $(call gb_Library_add_cxxobjects,gcc3_uno,\
+ bridges/source/cpp_uno/shared/cppinterfaceproxy \
+ , $(gb_COMPILERNOOPTFLAGS) $(gb_LinkTarget_EXCEPTIONFLAGS) \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/bridges/Module_bridges.mk b/bridges/Module_bridges.mk
index 800c8ca17f1a..118e82f4466b 100644
--- a/bridges/Module_bridges.mk
+++ b/bridges/Module_bridges.mk
@@ -73,6 +73,9 @@ $(eval $(call gb_Module_add_targets,bridges,\
$(if $(filter GCCMACOSXI,$(COM)$(OS)$(CPU)),\
Library_gcc3_macosx_intel \
) \
+ $(if $(filter GCCMACOSXX,$(COM)$(OS)$(CPU)),\
+ Library_gcc3_macosx_x86-64 \
+ ) \
$(if $(filter GCCMACOSXP,$(COM)$(OS)$(CPU)),\
Library_gcc3_macosx_powerpc \
) \
diff --git a/bridges/inc/bridges/cpp_uno/shared/vtablefactory.hxx b/bridges/inc/bridges/cpp_uno/shared/vtablefactory.hxx
index bc43fb48e519..cc6ef427ea7f 100644
--- a/bridges/inc/bridges/cpp_uno/shared/vtablefactory.hxx
+++ b/bridges/inc/bridges/cpp_uno/shared/vtablefactory.hxx
@@ -39,7 +39,8 @@
/*See: http://people.redhat.com/drepper/selinux-mem.html*/
#if defined(LINUX) || defined(OPENBSD) || defined(FREEBSD) \
- || defined(NETBSD) || defined(DRAGONFLY) || defined (ANDROID)
+ || defined(NETBSD) || defined(DRAGONFLY) || defined (ANDROID) \
+ || (defined(MACOSX) && defined(__LP64__))
#define USE_DOUBLE_MMAP
#endif
diff --git a/bridges/source/cpp_uno/gcc3_macosx_x86-64/abi.cxx b/bridges/source/cpp_uno/gcc3_macosx_x86-64/abi.cxx
new file mode 100644
index 000000000000..9fb14a90082c
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_macosx_x86-64/abi.cxx
@@ -0,0 +1,330 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+// This is an implementation of the x86-64 ABI as described in 'System V
+// Application Binary Interface, AMD64 Architecture Processor Supplement'
+// (http://www.x86-64.org/documentation/abi-0.95.pdf)
+//
+// The code in this file is a modification of src/x86/ffi64.c from libffi
+// (http://sources.redhat.com/libffi/) which is under the following license:
+
+/* -----------------------------------------------------------------------
+ ffi.c - Copyright (c) 2002 Bo Thorsen <bo@suse.de>
+
+ x86-64 Foreign Function Interface
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ ``Software''), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+ ----------------------------------------------------------------------- */
+
+#include "sal/config.h"
+
+#include "abi.hxx"
+
+using namespace x86_64;
+
+/* Register class used for passing given 64bit part of the argument.
+ These represent classes as documented by the PS ABI, with the exception
+ of SSESF, SSEDF classes, that are basically SSE class, just gcc will
+ use SF or DFmode move instead of DImode to avoid reformating penalties.
+
+ Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
+ whenever possible (upper half does contain padding).
+ */
+enum x86_64_reg_class
+{
+ X86_64_NO_CLASS,
+ X86_64_INTEGER_CLASS,
+ X86_64_INTEGERSI_CLASS,
+ X86_64_SSE_CLASS,
+ X86_64_SSESF_CLASS,
+ X86_64_SSEDF_CLASS,
+ X86_64_SSEUP_CLASS,
+ X86_64_X87_CLASS,
+ X86_64_X87UP_CLASS,
+ X86_64_MEMORY_CLASS
+};
+
+#define MAX_CLASSES 4
+
+/* x86-64 register passing implementation. See x86-64 ABI for details. Goal
+ of this code is to classify each 8bytes of incoming argument by the register
+ class and assign registers accordingly. */
+
+/* Return the union class of CLASS1 and CLASS2.
+ See the x86-64 PS ABI for details. */
+
+static enum x86_64_reg_class
+merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
+ throw ()
+{
+ /* Rule #1: If both classes are equal, this is the resulting class. */
+ if (class1 == class2)
+ return class1;
+
+ /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
+ the other class. */
+ if (class1 == X86_64_NO_CLASS)
+ return class2;
+ if (class2 == X86_64_NO_CLASS)
+ return class1;
+
+ /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */
+ if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
+ return X86_64_MEMORY_CLASS;
+
+ /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
+ if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
+ || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
+ return X86_64_INTEGERSI_CLASS;
+ if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
+ || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
+ return X86_64_INTEGER_CLASS;
+
+ /* Rule #5: If one of the classes is X87 or X87UP class, MEMORY is used. */
+ if (class1 == X86_64_X87_CLASS || class1 == X86_64_X87UP_CLASS
+ || class2 == X86_64_X87_CLASS || class2 == X86_64_X87UP_CLASS)
+ return X86_64_MEMORY_CLASS;
+
+ /* Rule #6: Otherwise class SSE is used. */
+ return X86_64_SSE_CLASS;
+}
+
+/* Classify the argument of type TYPE and mode MODE.
+ CLASSES will be filled by the register class used to pass each word
+ of the operand. The number of words is returned. In case the parameter
+ should be passed in memory, 0 is returned. As a special case for zero
+ sized containers, classes[0] will be NO_CLASS and 1 is returned.
+
+ See the x86-64 PS ABI for details.
+*/
+static int
+classify_argument( typelib_TypeDescriptionReference *pTypeRef, enum x86_64_reg_class classes[], int byteOffset ) throw ()
+{
+ switch ( pTypeRef->eTypeClass )
+ {
+ case typelib_TypeClass_VOID:
+ classes[0] = X86_64_NO_CLASS;
+ return 1;
+ case typelib_TypeClass_CHAR:
+ case typelib_TypeClass_BOOLEAN:
+ case typelib_TypeClass_BYTE:
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ case typelib_TypeClass_ENUM:
+ if ( ( byteOffset % 8 + pTypeRef->pType->nSize ) <= 4 )
+ classes[0] = X86_64_INTEGERSI_CLASS;
+ else
+ classes[0] = X86_64_INTEGER_CLASS;
+ return 1;
+ case typelib_TypeClass_FLOAT:
+ if ( ( byteOffset % 8 ) == 0 )
+ classes[0] = X86_64_SSESF_CLASS;
+ else
+ classes[0] = X86_64_SSE_CLASS;
+ return 1;
+ case typelib_TypeClass_DOUBLE:
+ classes[0] = X86_64_SSEDF_CLASS;
+ return 1;
+ /*case LONGDOUBLE:
+ classes[0] = X86_64_X87_CLASS;
+ classes[1] = X86_64_X87UP_CLASS;
+ return 2;*/
+ case typelib_TypeClass_STRING:
+ case typelib_TypeClass_TYPE:
+ case typelib_TypeClass_ANY:
+ case typelib_TypeClass_TYPEDEF:
+ case typelib_TypeClass_UNION:
+ case typelib_TypeClass_SEQUENCE:
+ case typelib_TypeClass_ARRAY:
+ case typelib_TypeClass_INTERFACE:
+ return 0;
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ typelib_TypeDescription * pTypeDescr = 0;
+ TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
+
+ const int UNITS_PER_WORD = 8;
+ int words = ( pTypeDescr->nSize + UNITS_PER_WORD - 1 ) / UNITS_PER_WORD;
+ enum x86_64_reg_class subclasses[MAX_CLASSES];
+
+ /* If the struct is larger than 16 bytes, pass it on the stack. */
+ if ( pTypeDescr->nSize > 16 )
+ {
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ return 0;
+ }
+
+ for ( int i = 0; i < words; i++ )
+ classes[i] = X86_64_NO_CLASS;
+
+ const typelib_CompoundTypeDescription *pStruct = reinterpret_cast<const typelib_CompoundTypeDescription*>( pTypeDescr );
+
+ /* Merge the fields of structure. */
+ for ( sal_Int32 nMember = 0; nMember < pStruct->nMembers; ++nMember )
+ {
+ typelib_TypeDescriptionReference *pTypeInStruct = pStruct->ppTypeRefs[ nMember ];
+ int offset = byteOffset + pStruct->pMemberOffsets[ nMember ];
+
+ int num = classify_argument( pTypeInStruct, subclasses, offset );
+
+ if ( num == 0 )
+ {
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ return 0;
+ }
+
+ for ( int i = 0; i < num; i++ )
+ {
+ int pos = offset / 8;
+ classes[i + pos] = merge_classes( subclasses[i], classes[i + pos] );
+ }
+ }
+
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+
+ /* Final merger cleanup. */
+ for ( int i = 0; i < words; i++ )
+ {
+ /* If one class is MEMORY, everything should be passed in
+ memory. */
+ if ( classes[i] == X86_64_MEMORY_CLASS )
+ return 0;
+
+ /* The X86_64_SSEUP_CLASS should be always preceded by
+ X86_64_SSE_CLASS. */
+ if ( classes[i] == X86_64_SSEUP_CLASS
+ && ( i == 0 || classes[i - 1] != X86_64_SSE_CLASS ) )
+ classes[i] = X86_64_SSE_CLASS;
+
+ /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */
+ if ( classes[i] == X86_64_X87UP_CLASS
+ && ( i == 0 || classes[i - 1] != X86_64_X87_CLASS ) )
+ classes[i] = X86_64_SSE_CLASS;
+ }
+ return words;
+ }
+
+ default:
+#if OSL_DEBUG_LEVEL > 1
+ OSL_TRACE( "Unhandled case: pType->eTypeClass == %d", pTypeRef->eTypeClass );
+#endif
+ OSL_ASSERT(0);
+ }
+ return 0; /* Never reached. */
+}
+
+/* Examine the argument and return set number of register required in each
+ class. Return 0 iff parameter should be passed in memory. */
+bool x86_64::examine_argument( typelib_TypeDescriptionReference *pTypeRef, bool bInReturn, int &nUsedGPR, int &nUsedSSE ) throw ()
+{
+ enum x86_64_reg_class classes[MAX_CLASSES];
+ int n;
+
+ n = classify_argument( pTypeRef, classes, 0 );
+
+ if ( n == 0 )
+ return false;
+
+ nUsedGPR = 0;
+ nUsedSSE = 0;
+ for ( n--; n >= 0; n-- )
+ switch ( classes[n] )
+ {
+ case X86_64_INTEGER_CLASS:
+ case X86_64_INTEGERSI_CLASS:
+ nUsedGPR++;
+ break;
+ case X86_64_SSE_CLASS:
+ case X86_64_SSESF_CLASS:
+ case X86_64_SSEDF_CLASS:
+ nUsedSSE++;
+ break;
+ case X86_64_NO_CLASS:
+ case X86_64_SSEUP_CLASS:
+ break;
+ case X86_64_X87_CLASS:
+ case X86_64_X87UP_CLASS:
+ if ( !bInReturn )
+ return false;
+ break;
+ default:
+#if OSL_DEBUG_LEVEL > 1
+ OSL_TRACE( "Unhandled case: classes[n] == %d", classes[n] );
+#endif
+ OSL_ASSERT(0);
+ }
+ return true;
+}
+
+bool x86_64::return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ) throw ()
+{
+ int g, s;
+
+ return examine_argument( pTypeRef, true, g, s ) == 0;
+}
+
+void x86_64::fill_struct( typelib_TypeDescriptionReference *pTypeRef, const sal_uInt64 *pGPR, const double *pSSE, void *pStruct ) throw ()
+{
+ enum x86_64_reg_class classes[MAX_CLASSES];
+ int n;
+
+ n = classify_argument( pTypeRef, classes, 0 );
+
+ sal_uInt64 *pStructAlign = reinterpret_cast<sal_uInt64 *>( pStruct );
+ for ( n--; n >= 0; n-- )
+ switch ( classes[n] )
+ {
+ case X86_64_INTEGER_CLASS:
+ case X86_64_INTEGERSI_CLASS:
+ *pStructAlign++ = *pGPR++;
+ break;
+ case X86_64_SSE_CLASS:
+ case X86_64_SSESF_CLASS:
+ case X86_64_SSEDF_CLASS:
+ *pStructAlign++ = *reinterpret_cast<const sal_uInt64 *>( pSSE++ );
+ break;
+ default:
+ break;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/bridges/source/cpp_uno/gcc3_macosx_x86-64/abi.hxx b/bridges/source/cpp_uno/gcc3_macosx_x86-64/abi.hxx
new file mode 100644
index 000000000000..ba3e8f24542f
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_macosx_x86-64/abi.hxx
@@ -0,0 +1,70 @@
+/* -*- 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.
+ *
+ ************************************************************************/
+
+#ifndef _BRIDGES_CPP_UNO_X86_64_ABI_HXX_
+#define _BRIDGES_CPP_UNO_X86_64_ABI_HXX_
+
+// This is an implementation of the x86-64 ABI as described in 'System V
+// Application Binary Interface, AMD64 Architecture Processor Supplement'
+// (http://www.x86-64.org/documentation/abi-0.95.pdf)
+
+#include <typelib/typedescription.hxx>
+
+namespace x86_64
+{
+
+/* 6 general purpose registers are used for parameter passing */
+const sal_uInt32 MAX_GPR_REGS = 6;
+
+/* 8 SSE registers are used for parameter passing */
+const sal_uInt32 MAX_SSE_REGS = 8;
+
+/* Count number of required registers.
+
+ Examine the argument and return set number of register required in each
+ class.
+
+ Return false iff parameter should be passed in memory.
+*/
+bool examine_argument( typelib_TypeDescriptionReference *pTypeRef, bool bInReturn, int &nUsedGPR, int &nUsedSSE ) throw ();
+
+/** Does function that returns this type use a hidden parameter, or registers?
+
+ The value can be returned either in a hidden 1st parameter (which is a
+ pointer to a structure allocated by the caller), or in registers (rax, rdx
+ for the integers, xmm0, xmm1 for the floating point numbers).
+*/
+bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ) throw ();
+
+void fill_struct( typelib_TypeDescriptionReference *pTypeRef, const sal_uInt64* pGPR, const double* pSSE, void *pStruct ) throw ();
+
+} // namespace x86_64
+
+#endif // _BRIDGES_CPP_UNO_X86_64_ABI_HXX_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/bridges/source/cpp_uno/gcc3_macosx_x86-64/call.s b/bridges/source/cpp_uno/gcc3_macosx_x86-64/call.s
new file mode 100644
index 000000000000..8b8072ff049c
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_macosx_x86-64/call.s
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+ .text
+ .align 4, 0x90
+ .globl _privateSnippetExecutor
+_privateSnippetExecutor:
+ .cfi_startproc
+.LFB3:
+ pushq %rbp
+.LCFI0:
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+.LCFI1:
+ subq $160, %rsp
+.LCFI2:
+ .cfi_def_cfa_register %rbp
+ movq %r10, -152(%rbp) # Save (nVtableOffset << 32) + nFunctionIndex
+
+ movq %rdi, -112(%rbp) # Save GP registers
+ movq %rsi, -104(%rbp)
+ movq %rdx, -96(%rbp)
+ movq %rcx, -88(%rbp)
+ movq %r8 , -80(%rbp)
+ movq %r9 , -72(%rbp)
+
+ movsd %xmm0, -64(%rbp) # Save FP registers
+ movsd %xmm1, -56(%rbp)
+ movsd %xmm2, -48(%rbp)
+ movsd %xmm3, -40(%rbp)
+ movsd %xmm4, -32(%rbp)
+ movsd %xmm5, -24(%rbp)
+ movsd %xmm6, -16(%rbp)
+ movsd %xmm7, -8(%rbp)
+
+ leaq -144(%rbp), %r9 # 6th param: sal_uInt64 * pRegisterReturn
+ leaq 16(%rbp), %r8 # 5rd param: void ** ovrflw
+ leaq -64(%rbp), %rcx # 4th param: void ** fpreg
+ leaq -112(%rbp), %rdx # 3rd param: void ** gpreg
+ movl -148(%rbp), %esi # 2nd param: sal_int32 nVtableOffset
+ movl -152(%rbp), %edi # 1st param: sal_int32 nFunctionIndex
+
+ call _cpp_vtable_call
+
+ cmp $10, %rax # typelib_TypeClass_FLOAT
+ je .Lfloat
+ cmp $11, %rax # typelib_TypeClass_DOUBLE
+ je .Lfloat
+
+ movq -144(%rbp), %rax # Return value (int case)
+ movq -136(%rbp), %rdx # Return value (int case)
+ movq -144(%rbp), %xmm0 # Return value (int case)
+ movq -136(%rbp), %xmm1 # Return value (int case)
+ jmp .Lfinish
+.Lfloat:
+ movlpd -144(%rbp), %xmm0 # Return value (float/double case)
+
+.Lfinish:
+ leave
+ ret
+ .cfi_endproc
+
+.subsections_via_symbols
diff --git a/bridges/source/cpp_uno/gcc3_macosx_x86-64/callvirtualmethod.cxx b/bridges/source/cpp_uno/gcc3_macosx_x86-64/callvirtualmethod.cxx
new file mode 100644
index 000000000000..57d039595982
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_macosx_x86-64/callvirtualmethod.cxx
@@ -0,0 +1,173 @@
+/* -*- 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 "sal/config.h"
+
+#include <cstring>
+
+#include "cppu/macros.hxx"
+#include "sal/types.h"
+#include "typelib/typeclass.h"
+#include "typelib/typedescription.h"
+
+#include "abi.hxx"
+#include "callvirtualmethod.hxx"
+
+// The call instruction within the asm block of callVirtualMethod may throw
+// exceptions. At least GCC 4.7.0 with -O0 would create (unnecessary)
+// .gcc_exception_table call-site table entries around all other calls in this
+// function that can throw, leading to std::terminate if the asm call throws an
+// exception and the unwinding C++ personality routine finds the unexpected hole
+// in the .gcc_exception_table. Therefore, make sure this function explicitly
+// only calls nothrow-functions (so GCC 4.7.0 with -O0 happens to not create a
+// .gcc_exception_table section at all for this function). For some reason,
+// this also needs to be in a source file of its own.
+//
+// Also, this file should be compiled with -fnon-call-exceptions, and ideally
+// there would be a way to tell the compiler that the asm block contains calls
+// to functions that can potentially throw; see the mail thread starting at
+// <http://gcc.gnu.org/ml/gcc/2012-03/msg00454.html> "C++: Letting compiler know
+// asm block can call function that can throw?"
+
+void CPPU_CURRENT_NAMESPACE::callVirtualMethod(
+ void * pThis, sal_uInt32 nVtableIndex, void * pRegisterReturn,
+ typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn,
+ sal_uInt64 *pStack, sal_uInt32 nStack, sal_uInt64 *pGPR, sal_uInt32 nGPR,
+ double * pFPR, sal_uInt32 nFPR)
+{
+ // Should not happen, but...
+ if ( nFPR > x86_64::MAX_SSE_REGS )
+ nFPR = x86_64::MAX_SSE_REGS;
+ if ( nGPR > x86_64::MAX_GPR_REGS )
+ nGPR = x86_64::MAX_GPR_REGS;
+
+ // Get pointer to method
+ sal_uInt64 pMethod = *((sal_uInt64 *)pThis);
+ pMethod += 8 * nVtableIndex;
+ pMethod = *((sal_uInt64 *)pMethod);
+
+ // Load parameters to stack, if necessary
+ if ( nStack )
+ {
+ // 16-bytes aligned
+ sal_uInt32 nStackBytes = ( ( nStack + 1 ) >> 1 ) * 16;
+ sal_uInt64 *pCallStack = (sal_uInt64 *) __builtin_alloca( nStackBytes );
+ std::memcpy( pCallStack, pStack, nStackBytes );
+ }
+
+ // Return values
+ sal_uInt64 rax;
+ sal_uInt64 rdx;
+ double xmm0;
+ double xmm1;
+
+ asm volatile (
+
+ // Fill the xmm registers
+ "movq %6, %%rax\n\t"
+
+ "movsd (%%rax), %%xmm0\n\t"
+ "movsd 8(%%rax), %%xmm1\n\t"
+ "movsd 16(%%rax), %%xmm2\n\t"
+ "movsd 24(%%rax), %%xmm3\n\t"
+ "movsd 32(%%rax), %%xmm4\n\t"
+ "movsd 40(%%rax), %%xmm5\n\t"
+ "movsd 48(%%rax), %%xmm6\n\t"
+ "movsd 56(%%rax), %%xmm7\n\t"
+
+ // Fill the general purpose registers
+ "movq %5, %%rax\n\t"
+
+ "movq (%%rax), %%rdi\n\t"
+ "movq 8(%%rax), %%rsi\n\t"
+ "movq 16(%%rax), %%rdx\n\t"
+ "movq 24(%%rax), %%rcx\n\t"
+ "movq 32(%%rax), %%r8\n\t"
+ "movq 40(%%rax), %%r9\n\t"
+
+ // Perform the call
+ "movq %4, %%r11\n\t"
+ "movq %7, %%rax\n\t"
+ "call *%%r11\n\t"
+
+ // Fill the return values
+ "movq %%rax, %0\n\t"
+ "movq %%rdx, %1\n\t"
+ "movsd %%xmm0, %2\n\t"
+ "movsd %%xmm1, %3\n\t"
+ : "=m" ( rax ), "=m" ( rdx ), "=m" ( xmm0 ), "=m" ( xmm1 )
+ : "m" ( pMethod ), "m" ( pGPR ), "m" ( pFPR ), "m" ( nFPR )
+ : "rax", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r10", "r11",
+ "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
+ "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
+ );
+
+ switch (pReturnTypeRef->eTypeClass)
+ {
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = rax;
+ break;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ case typelib_TypeClass_ENUM:
+ *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt32*>( &rax );
+ break;
+ case typelib_TypeClass_CHAR:
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ *reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt16*>( &rax );
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ case typelib_TypeClass_BYTE:
+ *reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt8*>( &rax );
+ break;
+ case typelib_TypeClass_FLOAT:
+ case typelib_TypeClass_DOUBLE:
+ *reinterpret_cast<double *>( pRegisterReturn ) = xmm0;
+ break;
+ default:
+ {
+ sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize;
+ if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0)
+ {
+ sal_uInt64 longs[2];
+ longs[0] = rax;
+ longs[1] = rdx;
+
+ double doubles[2];
+ doubles[0] = xmm0;
+ doubles[1] = xmm1;
+ x86_64::fill_struct( pReturnTypeRef, &longs[0], &doubles[0], pRegisterReturn);
+ }
+ break;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/bridges/source/cpp_uno/gcc3_macosx_x86-64/callvirtualmethod.hxx b/bridges/source/cpp_uno/gcc3_macosx_x86-64/callvirtualmethod.hxx
new file mode 100644
index 000000000000..2a776b9e87e6
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_macosx_x86-64/callvirtualmethod.hxx
@@ -0,0 +1,50 @@
+/* -*- 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.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_GCC3_LINUX_X86_64_CALLVIRTUALMETHOD_HXX
+#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_GCC3_LINUX_X86_64_CALLVIRTUALMETHOD_HXX
+
+#include "sal/config.h"
+
+#include "cppu/macros.hxx"
+#include "sal/types.h"
+#include "typelib/typedescription.h"
+
+namespace CPPU_CURRENT_NAMESPACE {
+
+void callVirtualMethod(
+ void * pThis, sal_uInt32 nVtableIndex, void * pRegisterReturn,
+ typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn,
+ sal_uInt64 *pStack, sal_uInt32 nStack, sal_uInt64 *pGPR, sal_uInt32 nGPR,
+ double * pFPR, sal_uInt32 nFPR);
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/bridges/source/cpp_uno/gcc3_macosx_x86-64/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_macosx_x86-64/cpp2uno.cxx
new file mode 100644
index 000000000000..89ab4624911a
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_macosx_x86-64/cpp2uno.cxx
@@ -0,0 +1,525 @@
+/* -*- 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 <stdio.h>
+#include <stdlib.h>
+#include <boost/unordered_map.hpp>
+
+#include <rtl/alloc.h>
+#include <osl/mutex.hxx>
+
+#include <com/sun/star/uno/genfunc.hxx>
+#include "com/sun/star/uno/RuntimeException.hpp"
+#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 "abi.hxx"
+#include "share.hxx"
+
+using namespace ::osl;
+using namespace ::rtl;
+using namespace ::com::sun::star::uno;
+
+//==================================================================================================
+
+// Perform the UNO call
+//
+// We must convert the parameters stored in gpreg, fpreg and ovrflw to UNO
+// arguments and call pThis->getUnoI()->pDispatcher.
+//
+// gpreg: [ret *], this, [gpr params]
+// fpreg: [fpr params]
+// ovrflw: [gpr or fpr params (properly aligned)]
+//
+// [ret *] is present when we are returning a structure bigger than 16 bytes
+// Simple types are returned in rax, rdx (int), or xmm0, xmm1 (fp).
+// Similarly structures <= 16 bytes are in rax, rdx, xmm0, xmm1 as necessary.
+static typelib_TypeClass 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 ** gpreg, void ** fpreg, void ** ovrflw,
+ sal_uInt64 * pRegisterReturn /* space for register return */ )
+{
+ unsigned int nr_gpr = 0; //number of gpr registers used
+ unsigned int nr_fpr = 0; //number of fpr registers used
+
+ // 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_64::return_in_hidden_param( pReturnTypeRef ) )
+ {
+ pCppReturn = *gpreg++;
+ nr_gpr++;
+
+ pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
+ ? alloca( pReturnTypeDescr->nSize )
+ : pCppReturn ); // direct way
+ }
+ else
+ pUnoReturn = pRegisterReturn; // direct way for simple types
+ }
+
+ // pop this
+ gpreg++;
+ nr_gpr++;
+
+ // stack space
+ // 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];
+
+ int nUsedGPR = 0;
+ int nUsedSSE = 0;
+#if OSL_DEBUG_LEVEL > 0
+ bool bFitsRegisters =
+#endif
+ x86_64::examine_argument( rParam.pTypeRef, false, nUsedGPR, nUsedSSE );
+ if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( rParam.pTypeRef ) ) // value
+ {
+ // Simple types must fit exactly one register on x86_64
+ OSL_ASSERT( bFitsRegisters && ( ( nUsedSSE == 1 && nUsedGPR == 0 ) || ( nUsedSSE == 0 && nUsedGPR == 1 ) ) );
+
+ if ( nUsedSSE == 1 )
+ {
+ if ( nr_fpr < x86_64::MAX_SSE_REGS )
+ {
+ pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++;
+ nr_fpr++;
+ }
+ else
+ pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
+ }
+ else if ( nUsedGPR == 1 )
+ {
+ if ( nr_gpr < x86_64::MAX_GPR_REGS )
+ {
+ pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++;
+ nr_gpr++;
+ }
+ else
+ pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
+ }
+ }
+ else // struct <= 16 bytes || ptr to complex value || ref
+ {
+ typelib_TypeDescription * pParamTypeDescr = 0;
+ TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
+
+ void *pCppStack;
+ if ( nr_gpr < x86_64::MAX_GPR_REGS )
+ {
+ pCppArgs[nPos] = pCppStack = *gpreg++;
+ nr_gpr++;
+ }
+ else
+ pCppArgs[nPos] = pCppStack = *ovrflw++;
+
+ 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;
+ }
+ else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ) ) // is in/inout
+ {
+ uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
+ 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] = pCppStack;
+ // no longer needed
+ TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+ }
+ }
+ }
+
+ // 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
+ // is here for dummy
+ return typelib_TypeClass_VOID;
+ }
+ 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 );
+ }
+ // complex return ptr is set to return reg
+ *(void **)pRegisterReturn = pCppReturn;
+ }
+ if ( pReturnTypeDescr )
+ {
+ typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
+ TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
+ return eRet;
+ }
+ else
+ return typelib_TypeClass_VOID;
+ }
+}
+
+
+//==================================================================================================
+extern "C" typelib_TypeClass cpp_vtable_call(
+ sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
+ void ** gpreg, void ** fpreg, void ** ovrflw,
+ sal_uInt64 * pRegisterReturn /* space for register return */ )
+{
+ // gpreg: [ret *], this, [other gpr params]
+ // fpreg: [fpr params]
+ // ovrflw: [gpr or fpr params (properly aligned)]
+ void * pThis;
+ if ( nFunctionIndex & 0x80000000 )
+ {
+ nFunctionIndex &= 0x7fffffff;
+ pThis = gpreg[1];
+ }
+ else
+ {
+ pThis = gpreg[0];
+ }
+ pThis = static_cast<char *>( pThis ) - nVtableOffset;
+
+ 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!\n" );
+ if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex )
+ {
+ throw RuntimeException( OUString(RTL_CONSTASCII_USTRINGPARAM("illegal vtable index!")),
+ reinterpret_cast<XInterface *>( pCppI ) );
+ }
+
+ // determine called method
+ sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
+ OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!\n" );
+
+ TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
+
+ typelib_TypeClass eRet;
+ switch ( aMemberDescr.get()->eTypeClass )
+ {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ {
+ typelib_TypeDescriptionReference *pAttrTypeRef =
+ reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef;
+
+ if ( pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
+ {
+ // is GET method
+ eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef,
+ 0, 0, // no params
+ gpreg, fpreg, ovrflw, pRegisterReturn );
+ }
+ else
+ {
+ // is SET method
+ typelib_MethodParameter aParam;
+ aParam.pTypeRef = pAttrTypeRef;
+ aParam.bIn = sal_True;
+ aParam.bOut = sal_False;
+
+ eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
+ 0, // indicates void return
+ 1, &aParam,
+ gpreg, fpreg, ovrflw, pRegisterReturn );
+ }
+ break;
+ }
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ // is METHOD
+ switch ( nFunctionIndex )
+ {
+ case 1: // acquire()
+ pCppI->acquireProxy(); // non virtual call!
+ eRet = typelib_TypeClass_VOID;
+ break;
+ case 2: // release()
+ pCppI->releaseProxy(); // non virtual call!
+ eRet = typelib_TypeClass_VOID;
+ break;
+ case 0: // queryInterface() opt
+ {
+ typelib_TypeDescription * pTD = 0;
+ TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( gpreg[2] )->getTypeLibType() );
+ if ( pTD )
+ {
+ XInterface * pInterface = 0;
+ (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
+ ( pCppI->getBridge()->getCppEnv(),
+ (void **)&pInterface,
+ pCppI->getOid().pData,
+ reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
+
+ if ( pInterface )
+ {
+ ::uno_any_construct( reinterpret_cast<uno_Any *>( gpreg[0] ),
+ &pInterface, pTD, cpp_acquire );
+
+ pInterface->release();
+ TYPELIB_DANGER_RELEASE( pTD );
+
+ reinterpret_cast<void **>( pRegisterReturn )[0] = gpreg[0];
+ eRet = typelib_TypeClass_ANY;
+ break;
+ }
+ TYPELIB_DANGER_RELEASE( pTD );
+ }
+ } // else perform queryInterface()
+ default:
+ {
+ typelib_InterfaceMethodTypeDescription *pMethodTD =
+ reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
+
+ eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
+ pMethodTD->pReturnTypeRef,
+ pMethodTD->nParams,
+ pMethodTD->pParams,
+ gpreg, fpreg, ovrflw, pRegisterReturn );
+ }
+ }
+ break;
+ }
+ default:
+ {
+ throw RuntimeException( OUString(RTL_CONSTASCII_USTRINGPARAM("no member description found!")),
+ reinterpret_cast<XInterface *>( pCppI ) );
+ }
+ }
+
+ return eRet;
+}
+
+//==================================================================================================
+extern "C" void privateSnippetExecutor( ... );
+
+const int codeSnippetSize = 24;
+
+// Generate a trampoline that redirects method calls to
+// privateSnippetExecutor().
+//
+// privateSnippetExecutor() saves all the registers that are used for
+// parameter passing on x86_64, and calls the cpp_vtable_call().
+// When it returns, privateSnippetExecutor() sets the return value.
+//
+// Note: The code snippet we build here must not create a stack frame,
+// otherwise the UNO exceptions stop working thanks to non-existing
+// unwinding info.
+unsigned char * codeSnippet( unsigned char * code,
+ sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
+ bool bHasHiddenParam ) SAL_THROW(())
+{
+ sal_uInt64 nOffsetAndIndex = ( ( (sal_uInt64) nVtableOffset ) << 32 ) | ( (sal_uInt64) nFunctionIndex );
+
+ if ( bHasHiddenParam )
+ nOffsetAndIndex |= 0x80000000;
+
+ // movq $<nOffsetAndIndex>, %r10
+ *reinterpret_cast<sal_uInt16 *>( code ) = 0xba49;
+ *reinterpret_cast<sal_uInt64 *>( code + 2 ) = nOffsetAndIndex;
+
+ // movq $<address of the privateSnippetExecutor>, %r11
+ *reinterpret_cast<sal_uInt16 *>( code + 10 ) = 0xbb49;
+ *reinterpret_cast<sal_uInt64 *>( code + 12 ) = reinterpret_cast<sal_uInt64>( privateSnippetExecutor );
+
+ // jmpq *%r11
+ *reinterpret_cast<sal_uInt32 *>( code + 20 ) = 0x00e3ff49;
+
+#if OSL_DEBUG_LEVEL > 1
+ fprintf(stderr,
+ "==> codeSnippet, functionIndex=%d%s, vtableOffset=%d\n",
+ nFunctionIndex, (bHasHiddenParam ? "|0x80000000":""), nVtableOffset);
+#endif
+
+ return code + codeSnippetSize;
+}
+
+//==================================================================================================
+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 (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
+}
+
+//==================================================================================================
+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, sal_PtrDiff writetoexecdiff,
+ typelib_InterfaceTypeDescription const * type, sal_Int32 nFunctionOffset,
+ sal_Int32 functionCount, sal_Int32 nVtableOffset )
+{
+ (*slots) -= functionCount;
+ Slot * s = *slots;
+ for ( sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos )
+ {
+ typelib_TypeDescription * pTD = 0;
+
+ TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] );
+ OSL_ASSERT( pTD );
+
+ if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass )
+ {
+ typelib_InterfaceAttributeTypeDescription *pAttrTD =
+ reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
+
+ // get method
+ (s++)->fn = code + writetoexecdiff;
+ code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
+ x86_64::return_in_hidden_param( pAttrTD->pAttributeTypeRef ) );
+
+ if ( ! pAttrTD->bReadOnly )
+ {
+ // set method
+ (s++)->fn = code + writetoexecdiff;
+ code = codeSnippet( code, nFunctionOffset++, nVtableOffset, false );
+ }
+ }
+ else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass )
+ {
+ typelib_InterfaceMethodTypeDescription *pMethodTD =
+ reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
+
+ (s++)->fn = code + writetoexecdiff;
+ code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
+ x86_64::return_in_hidden_param( pMethodTD->pReturnTypeRef ) );
+ }
+ else
+ OSL_ASSERT( false );
+
+ TYPELIB_DANGER_RELEASE( pTD );
+ }
+ return code;
+}
+
+//==================================================================================================
+void bridges::cpp_uno::shared::VtableFactory::flushCode(
+ SAL_UNUSED_PARAMETER unsigned char const *,
+ SAL_UNUSED_PARAMETER unsigned char const * )
+{}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/bridges/source/cpp_uno/gcc3_macosx_x86-64/except.cxx b/bridges/source/cpp_uno/gcc3_macosx_x86-64/except.cxx
new file mode 100644
index 000000000000..03a7ca5b36db
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_macosx_x86-64/except.cxx
@@ -0,0 +1,389 @@
+/* -*- 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 <stdio.h>
+#include <string.h>
+#include <dlfcn.h>
+
+#include <cxxabi.h>
+#ifndef _GLIBCXX_CDTOR_CALLABI // new in GCC 4.7 cxxabi.h
+#define _GLIBCXX_CDTOR_CALLABI
+#endif
+
+#include <boost/unordered_map.hpp>
+
+#include <sal/log.hxx>
+#include <rtl/instance.hxx>
+#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
+{
+
+#if MACOSX_SDK_VERSION >= 1070
+
+// MacOSX10.4u.sdk/usr/include/c++/4.0.0/cxxabi.h defined
+// __cxxabiv1::__class_type_info and __cxxabiv1::__si_class_type_info but
+// MacOSX10.7.sdk/usr/include/cxxabi.h no longer does, so instances of those
+// classes need to be created manually:
+
+// std::type_info defined in <typeinfo> offers a protected ctor:
+struct FAKE_type_info: public std::type_info {
+ FAKE_type_info(char const * name): type_info(name) {}
+};
+
+// Modeled after __cxxabiv1::__si_class_type_info defined in
+// MacOSX10.4u.sdk/usr/include/c++/4.0.0/cxxabi.h (i.e.,
+// abi::__si_class_type_info documented at
+// <http://www.codesourcery.com/public/cxx-abi/abi.html#rtti>):
+struct FAKE_si_class_type_info: public FAKE_type_info {
+ FAKE_si_class_type_info(char const * name, std::type_info const * theBase):
+ FAKE_type_info(name), base(theBase) {}
+
+ std::type_info const * base;
+ // actually a __cxxabiv1::__class_type_info pointer
+};
+
+struct Base {};
+struct Derived: Base {};
+
+std::type_info * create_FAKE_class_type_info(char const * name) {
+ std::type_info * p = new FAKE_type_info(name);
+ // cxxabiv1::__class_type_info has no data members in addition to
+ // std::type_info
+ *reinterpret_cast< void ** >(p) = *reinterpret_cast< void * const * >(
+ &typeid(Base));
+ // copy correct __cxxabiv1::__class_type_info vtable into place
+ return p;
+}
+
+std::type_info * create_FAKE_si_class_type_info(
+ char const * name, std::type_info const * base)
+{
+ std::type_info * p = new FAKE_si_class_type_info(name, base);
+ *reinterpret_cast< void ** >(p) = *reinterpret_cast< void * const * >(
+ &typeid(Derived));
+ // copy correct __cxxabiv1::__si_class_type_info vtable into place
+ return p;
+}
+
+#endif
+
+//==================================================================================================
+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(())
+#if defined(FREEBSD) && __FreeBSD_version < 702104
+ : m_hApp( dlopen( 0, RTLD_NOW | RTLD_GLOBAL ) )
+#else
+ : m_hApp( dlopen( 0, RTLD_LAZY ) )
+#endif
+{
+}
+//__________________________________________________________________________________________________
+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() );
+#if defined(FREEBSD) && __FreeBSD_version < 702104 /* #i22253# */
+ rtti = (type_info *)dlsym( RTLD_DEFAULT, symName.getStr() );
+#else
+ rtti = (type_info *)dlsym( m_hApp, symName.getStr() );
+#endif
+
+ if (rtti)
+ {
+ pair< t_rtti_map::iterator, bool > insertion (
+ m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
+ SAL_WARN_IF( !insertion.second, "bridges", "key " << unoName << " already in rtti map" );
+ }
+ 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 );
+#if MACOSX_SDK_VERSION < 1070
+ rtti = new __si_class_type_info(
+ strdup( rttiName ), (__class_type_info *)base_rtti );
+#else
+ rtti = create_FAKE_si_class_type_info(
+ strdup( rttiName ), base_rtti );
+#endif
+ }
+ else
+ {
+ // this class has no base class
+#if MACOSX_SDK_VERSION < 1070
+ rtti = new __class_type_info( strdup( rttiName ) );
+#else
+ rtti = create_FAKE_class_type_info( strdup( rttiName ) );
+#endif
+ }
+
+ pair< t_rtti_map::iterator, bool > insertion (
+ m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
+ SAL_WARN_IF( !insertion.second, "bridges", "key " << unoName << " already in generated rtti map" );
+ }
+ else // taking already generated rtti
+ {
+ rtti = iFind2->second;
+ }
+ }
+ }
+ else
+ {
+ rtti = iFind->second;
+ }
+
+ return rtti;
+}
+
+struct RTTISingleton: public rtl::Static< RTTI, RTTISingleton > {};
+
+//--------------------------------------------------------------------------------------------------
+extern "C" {
+static void _GLIBCXX_CDTOR_CALLABI 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
+ rtti = (type_info *)RTTISingleton::get().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_macosx_x86-64/share.hxx b/bridges/source/cpp_uno/gcc3_macosx_x86-64/share.hxx
new file mode 100644
index 000000000000..f84958b96368
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_macosx_x86-64/share.hxx
@@ -0,0 +1,104 @@
+/* -*- 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
+{
+
+// ----- 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;
+};
+
+struct __cxa_eh_globals
+{
+ __cxa_exception *caughtExceptions;
+ unsigned int uncaughtExceptions;
+};
+
+}
+
+extern "C" CPPU_CURRENT_NAMESPACE::__cxa_eh_globals *__cxa_get_globals () throw();
+
+namespace CPPU_CURRENT_NAMESPACE
+{
+
+// The following are in cxxabi.h since GCC 4.7 (they are wrapped in
+// CPPU_CURRENT_NAMESPACE here as different GCC versions have slightly different
+// declarations for them, e.g., with or without throw() specification, so would
+// complain about redeclarations of these somewhat implicitly declared
+// functions):
+#if __GNUC__ == 4 && __GNUC_MINOR__ <= 6
+extern "C" void *__cxa_allocate_exception(
+ std::size_t thrown_size ) throw();
+extern "C" void __cxa_throw (
+ void *thrown_exception, void *tinfo, void (*dest) (void *) ) __attribute__((noreturn));
+#endif
+
+// -----
+
+//==================================================================================================
+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_macosx_x86-64/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_macosx_x86-64/uno2cpp.cxx
new file mode 100644
index 000000000000..ff6fbdda7649
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_macosx_x86-64/uno2cpp.cxx
@@ -0,0 +1,459 @@
+/* -*- 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.
+ *
+ ************************************************************************/
+
+#if defined (FREEBSD) || defined(NETBSD) || defined(OPENBSD) || defined(DRAGONFLY)
+#include <stdlib.h>
+#else
+#include <alloca.h>
+#endif
+#include <exception>
+#include <typeinfo>
+
+#include "rtl/alloc.h"
+#include "rtl/ustrbuf.hxx"
+
+#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 "abi.hxx"
+#include "callvirtualmethod.hxx"
+#include "share.hxx"
+
+using namespace ::rtl;
+using namespace ::com::sun::star::uno;
+
+// Macros for easier insertion of values to registers or stack
+// pSV - pointer to the source
+// nr - order of the value [will be increased if stored to register]
+// pFPR, pGPR - pointer to the registers
+// pDS - pointer to the stack [will be increased if stored here]
+
+// The value in %xmm register is already prepared to be retrieved as a float,
+// thus we treat float and double the same
+#define INSERT_FLOAT_DOUBLE( pSV, nr, pFPR, pDS ) \
+ if ( nr < x86_64::MAX_SSE_REGS ) \
+ pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \
+ else \
+ *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim!
+
+#define INSERT_INT64( pSV, nr, pGPR, pDS ) \
+ if ( nr < x86_64::MAX_GPR_REGS ) \
+ pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \
+ else \
+ *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV );
+
+#define INSERT_INT32( pSV, nr, pGPR, pDS ) \
+ if ( nr < x86_64::MAX_GPR_REGS ) \
+ pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
+ else \
+ *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
+
+#define INSERT_INT16( pSV, nr, pGPR, pDS ) \
+ if ( nr < x86_64::MAX_GPR_REGS ) \
+ pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
+ else \
+ *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
+
+#define INSERT_INT8( pSV, nr, pGPR, pDS ) \
+ if ( nr < x86_64::MAX_GPR_REGS ) \
+ pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
+ else \
+ *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
+
+//==================================================================================================
+
+namespace {
+
+void appendCString(OUStringBuffer & buffer, char const * text) {
+ if (text != 0) {
+ buffer.append(
+ OStringToOUString(OString(text), RTL_TEXTENCODING_ISO_8859_1));
+ // use 8859-1 to avoid conversion failure
+ }
+}
+
+}
+
+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 )
+{
+ // Maxium space for [complex ret ptr], values | ptr ...
+ // (but will be used less - some of the values will be in pGPR and pFPR)
+ sal_uInt64 *pStack = (sal_uInt64 *)__builtin_alloca( (nParams + 3) * sizeof(sal_uInt64) );
+ sal_uInt64 *pStackStart = pStack;
+
+ sal_uInt64 pGPR[x86_64::MAX_GPR_REGS];
+ sal_uInt32 nGPR = 0;
+
+ double pFPR[x86_64::MAX_SSE_REGS];
+ sal_uInt32 nFPR = 0;
+
+ // 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 (see below)
+
+ bool bSimpleReturn = true;
+ if ( pReturnTypeDescr )
+ {
+ if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
+ bSimpleReturn = false;
+
+ if ( bSimpleReturn )
+ pCppReturn = pUnoReturn; // direct way for simple types
+ else
+ {
+ // complex return via ptr
+ pCppReturn = bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )?
+ __builtin_alloca( pReturnTypeDescr->nSize ) : pUnoReturn;
+ INSERT_INT64( &pCppReturn, nGPR, pGPR, pStack );
+ }
+ }
+
+ // Push "this" pointer
+ void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
+ INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack );
+
+ // 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] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr,
+ pThis->getBridge()->getUno2Cpp() );
+
+ switch (pParamTypeDescr->eTypeClass)
+ {
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack );
+ break;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ case typelib_TypeClass_ENUM:
+ INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack );
+ break;
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_CHAR:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack );
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ case typelib_TypeClass_BYTE:
+ INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack );
+ break;
+ case typelib_TypeClass_FLOAT:
+ case typelib_TypeClass_DOUBLE:
+ INSERT_FLOAT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, pStack );
+ break;
+ 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(
+ 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(
+ 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
+ {
+ pCppArgs[nPos] = pUnoArgs[nPos];
+ // no longer needed
+ TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+ }
+ INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack );
+ }
+ }
+
+ try
+ {
+ try {
+ CPPU_CURRENT_NAMESPACE::callVirtualMethod(
+ pAdjustedThisPtr, aVtableSlot.index,
+ pCppReturn, pReturnTypeRef, bSimpleReturn,
+ pStackStart, ( pStack - pStackStart ),
+ pGPR, nGPR,
+ pFPR, nFPR );
+ } catch (const Exception &) {
+ throw;
+ } catch (const std::exception & e) {
+ OUStringBuffer buf;
+ buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("C++ code threw "));
+ appendCString(buf, typeid(e).name());
+ buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(": "));
+ appendCString(buf, e.what());
+ throw RuntimeException(
+ buf.makeStringAndClear(), Reference< XInterface >());
+ } catch (...) {
+ throw RuntimeException(
+ OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "C++ code threw unknown exception")),
+ Reference< XInterface >());
+ }
+
+ *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 (...)
+ {
+ // fill uno exception
+ fillUnoException( __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 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);
+#if OSL_DEBUG_LEVEL > 0
+ typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
+#endif
+
+ switch (pMemberDescr->eTypeClass)
+ {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ {
+#if OSL_DEBUG_LEVEL > 0
+ // determine vtable call index
+ sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
+ OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
+#endif
+ 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, // get, then set method
+ pReturnTypeRef,
+ 1, &aParam,
+ pReturn, pArgs, ppException );
+
+ typelib_typedescriptionreference_release( pReturnTypeRef );
+ }
+
+ break;
+ }
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+#if OSL_DEBUG_LEVEL > 0
+ // determine vtable call index
+ sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
+ OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
+#endif
+ 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->getBridge()->getUnoEnv()->getRegisteredInterface)(
+ pThis->getBridge()->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: */