diff options
Diffstat (limited to 'editors/openoffice.org-3-RC/files/patch-i65467')
-rw-r--r-- | editors/openoffice.org-3-RC/files/patch-i65467 | 2718 |
1 files changed, 2718 insertions, 0 deletions
diff --git a/editors/openoffice.org-3-RC/files/patch-i65467 b/editors/openoffice.org-3-RC/files/patch-i65467 new file mode 100644 index 000000000000..cbaef34381fe --- /dev/null +++ b/editors/openoffice.org-3-RC/files/patch-i65467 @@ -0,0 +1,2718 @@ +--- bridges/prj/build.lst 8 Mar 2006 08:49:22 -0000 1.34 ++++ bridges/prj/build.lst 8 May 2006 21:26:08 -0000 +@@ -9,6 +9,7 @@ + br bridges\source\cpp_uno\gcc3_linux_intel nmake - u br_gcc3li br_cppuno_shared br_unotypes NULL + br bridges\source\cpp_uno\gcc3_freebsd_intel nmake - u br_gcc3fi br_cppuno_shared br_unotypes NULL + br bridges\source\cpp_uno\gcc3_linux_x86-64 nmake - u br_gcc3lx br_cppuno_shared br_unotypes NULL ++br bridges\source\cpp_uno\gcc3_freebsd_x86-64 nmake - u br_gcc3fx br_cppuno_shared br_unotypes NULL + br bridges\source\cpp_uno\gcc3_linux_powerpc nmake - u br_gcclp3 br_cppuno_shared br_unotypes NULL + br bridges\source\cpp_uno\gcc3_linux_s390 nmake - u br_gccl33 br_unotypes NULL + br bridges\source\cpp_uno\gcc3_linux_sparc nmake - u br_gccl3s br_unotypes br_cppuno_shared NULL +--- /dev/null Wed Dec 31 19:00:00 1969 ++++ bridges/source/cpp_uno/gcc3_freebsd_x86-64/abi.cxx Wed Mar 8 03:49:32 2006 +@@ -0,0 +1,808 @@ ++/************************************************************************* ++ * ++ * OpenOffice.org - a multi-platform office productivity suite ++ * ++ * $RCSfile$ ++ * ++ * $Revision$ ++ * ++ * last change: $Author$ $Date$ ++ * ++ * The Contents of this file are made available subject to ++ * the terms of GNU Lesser General Public License Version 2.1. ++ * ++ * ++ * GNU Lesser General Public License Version 2.1 ++ * ============================================= ++ * Copyright 2005 by Sun Microsystems, Inc. ++ * 901 San Antonio Road, Palo Alto, CA 94303, USA ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License version 2.1, as published by the Free Software Foundation. ++ * ++ * This library 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 for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ * ++ ************************************************************************/ ++ ++// 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 <abi.hxx> ++ ++#include <rtl/ustring.hxx> ++ ++using namespace x86_64; ++ ++typedef struct ++{ ++ /* Registers for argument passing. */ ++ long gpr[MAX_GPR_REGS]; ++ __int128_t sse[MAX_SSE_REGS]; ++ ++ /* Stack space for arguments. */ ++ char argspace[0]; ++} stackLayout; ++ ++/* 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 ++ ++#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1) ++ ++/* 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) ++{ ++ /* 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 &rByteOffset ) ++{ ++ /* First, align to the right place. */ ++ rByteOffset = ALIGN( rByteOffset, pTypeRef->pType->nAlignment ); ++ ++ 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 ( ( rByteOffset % 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 ( ( rByteOffset % 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 num = classify_argument( pTypeInStruct, subclasses, rByteOffset ); ++ ++ if ( num == 0 ) ++ { ++ TYPELIB_DANGER_RELEASE( pTypeDescr ); ++ return 0; ++ } ++ ++ for ( int i = 0; i < num; i++ ) ++ { ++ int pos = rByteOffset / 8; ++ classes[i + pos] = merge_classes( subclasses[i], classes[i + pos] ); ++ } ++ ++ if ( pTypeInStruct->eTypeClass != typelib_TypeClass_STRUCT ) ++ rByteOffset = pStruct->pMemberOffsets[ nMember ]; ++ } ++ ++ 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\n", 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 ) ++{ ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int offset = 0; ++ int n; ++ ++ n = classify_argument( pTypeRef, classes, offset ); ++ ++ 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\n", classes[n] ); ++#endif ++ OSL_ASSERT(0); ++ } ++ return true; ++} ++ ++bool x86_64::return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ) ++{ ++ int g, s; ++ ++ return examine_argument( pTypeRef, true, g, s ) == 0; ++} ++ ++void x86_64::fill_struct( typelib_TypeDescriptionReference *pTypeRef, void * const *pGPR, void * const *pSSE, void *pStruct ) ++{ ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int offset = 0; ++ int n; ++ ++ n = classify_argument( pTypeRef, classes, offset ); ++ ++ 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++ = *reinterpret_cast<sal_uInt64 *>( *pGPR++ ); ++ break; ++ case X86_64_SSE_CLASS: ++ case X86_64_SSESF_CLASS: ++ case X86_64_SSEDF_CLASS: ++ *pStructAlign++ = *reinterpret_cast<sal_uInt64 *>( *pSSE++ ); ++ break; ++ } ++} ++ ++#if 0 ++ ++/* Functions to load floats and double to an SSE register placeholder. */ ++extern void float2sse (float, __int128_t *); ++extern void double2sse (double, __int128_t *); ++extern void floatfloat2sse (void *, __int128_t *); ++ ++/* Functions to put the floats and doubles back. */ ++extern float sse2float (__int128_t *); ++extern double sse2double (__int128_t *); ++extern void sse2floatfloat(__int128_t *, void *); ++ ++/*@-exportheader@*/ ++void ++ffi_prep_args (stackLayout *stack, extended_cif *ecif) ++/*@=exportheader@*/ ++{ ++ int gprcount, ssecount, i, g, s; ++ void **p_argv; ++ void *argp = &stack->argspace; ++ ffi_type **p_arg; ++ ++ /* First check if the return value should be passed in memory. If so, ++ pass the pointer as the first argument. */ ++ gprcount = ssecount = 0; ++ if (ecif->cif->rtype->type != FFI_TYPE_VOID ++ && examine_argument (ecif->cif->rtype, 1, &g, &s) == 0) ++ (void *)stack->gpr[gprcount++] = ecif->rvalue; ++ ++ for (i=ecif->cif->nargs, p_arg=ecif->cif->arg_types, p_argv = ecif->avalue; ++ i!=0; i--, p_arg++, p_argv++) ++ { ++ int in_register = 0; ++ ++ switch ((*p_arg)->type) ++ { ++ case FFI_TYPE_SINT8: ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_POINTER: ++ if (gprcount < MAX_GPR_REGS) ++ { ++ stack->gpr[gprcount] = 0; ++ stack->gpr[gprcount++] = *(long long *)(*p_argv); ++ in_register = 1; ++ } ++ break; ++ ++ case FFI_TYPE_FLOAT: ++ if (ssecount < MAX_SSE_REGS) ++ { ++ float2sse (*(float *)(*p_argv), &stack->sse[ssecount++]); ++ in_register = 1; ++ } ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ if (ssecount < MAX_SSE_REGS) ++ { ++ double2sse (*(double *)(*p_argv), &stack->sse[ssecount++]); ++ in_register = 1; ++ } ++ break; ++ } ++ ++ if (in_register) ++ continue; ++ ++ /* Either all places in registers where filled, or this is a ++ type that potentially goes into a memory slot. */ ++ if (examine_argument (*p_arg, 0, &g, &s) == 0 ++ || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS) ++ { ++ /* Pass this argument in memory. */ ++ argp = (void *)ALIGN(argp, (*p_arg)->alignment); ++ memcpy (argp, *p_argv, (*p_arg)->size); ++ argp += (*p_arg)->size; ++ } ++ else ++ { ++ /* All easy cases are eliminated. Now fire the big guns. */ ++ ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int offset = 0, j, num; ++ void *a; ++ ++ num = classify_argument (*p_arg, classes, &offset); ++ for (j=0, a=*p_argv; j<num; j++, a+=8) ++ { ++ switch (classes[j]) ++ { ++ case X86_64_INTEGER_CLASS: ++ case X86_64_INTEGERSI_CLASS: ++ stack->gpr[gprcount++] = *(long long *)a; ++ break; ++ case X86_64_SSE_CLASS: ++ floatfloat2sse (a, &stack->sse[ssecount++]); ++ break; ++ case X86_64_SSESF_CLASS: ++ float2sse (*(float *)a, &stack->sse[ssecount++]); ++ break; ++ case X86_64_SSEDF_CLASS: ++ double2sse (*(double *)a, &stack->sse[ssecount++]); ++ break; ++ default: ++ abort(); ++ } ++ } ++ } ++ } ++} ++ ++/* Perform machine dependent cif processing. */ ++ffi_status ++ffi_prep_cif_machdep (ffi_cif *cif) ++{ ++ int gprcount, ssecount, i, g, s; ++ ++ gprcount = ssecount = 0; ++ ++ /* Reset the byte count. We handle this size estimation here. */ ++ cif->bytes = 0; ++ ++ /* If the return value should be passed in memory, pass the pointer ++ as the first argument. The actual memory isn't allocated here. */ ++ if (cif->rtype->type != FFI_TYPE_VOID ++ && examine_argument (cif->rtype, 1, &g, &s) == 0) ++ gprcount = 1; ++ ++ /* Go over all arguments and determine the way they should be passed. ++ If it's in a register and there is space for it, let that be so. If ++ not, add it's size to the stack byte count. */ ++ for (i=0; i<cif->nargs; i++) ++ { ++ if (examine_argument (cif->arg_types[i], 0, &g, &s) == 0 ++ || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS) ++ { ++ /* This is passed in memory. First align to the basic type. */ ++ cif->bytes = ALIGN(cif->bytes, cif->arg_types[i]->alignment); ++ ++ /* Stack arguments are *always* at least 8 byte aligned. */ ++ cif->bytes = ALIGN(cif->bytes, 8); ++ ++ /* Now add the size of this argument. */ ++ cif->bytes += cif->arg_types[i]->size; ++ } ++ else ++ { ++ gprcount += g; ++ ssecount += s; ++ } ++ } ++ ++ /* Set the flag for the closures return. */ ++ switch (cif->rtype->type) ++ { ++ case FFI_TYPE_VOID: ++ case FFI_TYPE_STRUCT: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_FLOAT: ++ case FFI_TYPE_DOUBLE: ++ case FFI_TYPE_LONGDOUBLE: ++ cif->flags = (unsigned) cif->rtype->type; ++ break; ++ ++ case FFI_TYPE_UINT64: ++ cif->flags = FFI_TYPE_SINT64; ++ break; ++ ++ default: ++ cif->flags = FFI_TYPE_INT; ++ break; ++ } ++ ++ return FFI_OK; ++} ++ ++typedef struct ++{ ++ long gpr[2]; ++ __int128_t sse[2]; ++ long double st0; ++} return_value; ++ ++//#endif ++ ++void ++ffi_fill_return_value (return_value *rv, extended_cif *ecif) ++{ ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int i = 0, num; ++ long *gpr = rv->gpr; ++ __int128_t *sse = rv->sse; ++ signed char sc; ++ signed short ss; ++ ++ /* This is needed because of the way x86-64 handles signed short ++ integers. */ ++ switch (ecif->cif->rtype->type) ++ { ++ case FFI_TYPE_SINT8: ++ sc = *(signed char *)gpr; ++ *(long long *)ecif->rvalue = (long long)sc; ++ return; ++ case FFI_TYPE_SINT16: ++ ss = *(signed short *)gpr; ++ *(long long *)ecif->rvalue = (long long)ss; ++ return; ++ default: ++ /* Just continue. */ ++ ; ++ } ++ ++ num = classify_argument (ecif->cif->rtype, classes, &i); ++ ++ if (num == 0) ++ /* Return in memory. */ ++ ecif->rvalue = (void *) rv->gpr[0]; ++ else if (num == 2 && classes[0] == X86_64_X87_CLASS && ++ classes[1] == X86_64_X87UP_CLASS) ++ /* This is a long double (this is easiest to handle this way instead ++ of an eightbyte at a time as in the loop below. */ ++ *((long double *)ecif->rvalue) = rv->st0; ++ else ++ { ++ void *a; ++ ++ for (i=0, a=ecif->rvalue; i<num; i++, a+=8) ++ { ++ switch (classes[i]) ++ { ++ case X86_64_INTEGER_CLASS: ++ case X86_64_INTEGERSI_CLASS: ++ *(long long *)a = *gpr; ++ gpr++; ++ break; ++ case X86_64_SSE_CLASS: ++ sse2floatfloat (sse++, a); ++ break; ++ case X86_64_SSESF_CLASS: ++ *(float *)a = sse2float (sse++); ++ break; ++ case X86_64_SSEDF_CLASS: ++ *(double *)a = sse2double (sse++); ++ break; ++ default: ++ abort(); ++ } ++ } ++ } ++} ++ ++//#if 0 ++ ++/*@-declundef@*/ ++/*@-exportheader@*/ ++extern void ffi_call_UNIX64(void (*)(stackLayout *, extended_cif *), ++ void (*) (return_value *, extended_cif *), ++ /*@out@*/ extended_cif *, ++ unsigned, /*@out@*/ unsigned *, void (*fn)()); ++/*@=declundef@*/ ++/*@=exportheader@*/ ++ ++void ffi_call(/*@dependent@*/ ffi_cif *cif, ++ void (*fn)(), ++ /*@out@*/ void *rvalue, ++ /*@dependent@*/ void **avalue) ++{ ++ extended_cif ecif; ++ int dummy; ++ ++ ecif.cif = cif; ++ ecif.avalue = avalue; ++ ++ /* If the return value is a struct and we don't have a return */ ++ /* value address then we need to make one */ ++ ++ if ((rvalue == NULL) && ++ (examine_argument (cif->rtype, 1, &dummy, &dummy) == 0)) ++ { ++ /*@-sysunrecog@*/ ++ ecif.rvalue = alloca(cif->rtype->size); ++ /*@=sysunrecog@*/ ++ } ++ else ++ ecif.rvalue = rvalue; ++ ++ /* Stack must always be 16byte aligned. Make it so. */ ++ cif->bytes = ALIGN(cif->bytes, 16); ++ ++ switch (cif->abi) ++ { ++ case FFI_SYSV: ++ /* Calling 32bit code from 64bit is not possible */ ++ FFI_ASSERT(0); ++ break; ++ ++ case FFI_UNIX64: ++ /*@-usedef@*/ ++ ffi_call_UNIX64 (ffi_prep_args, ffi_fill_return_value, &ecif, ++ cif->bytes, ecif.rvalue, fn); ++ /*@=usedef@*/ ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++extern void ffi_closure_UNIX64(void); ++ ++ffi_status ++ffi_prep_closure (ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*, void*, void**, void*), ++ void *user_data) ++{ ++ volatile unsigned short *tramp; ++ ++ /* FFI_ASSERT (cif->abi == FFI_OSF); */ ++ ++ tramp = (volatile unsigned short *) &closure->tramp[0]; ++ tramp[0] = 0xbb49; /* mov <code>, %r11 */ ++ tramp[5] = 0xba49; /* mov <data>, %r10 */ ++ tramp[10] = 0xff49; /* jmp *%r11 */ ++ tramp[11] = 0x00e3; ++ *(void * volatile *) &tramp[1] = ffi_closure_UNIX64; ++ *(void * volatile *) &tramp[6] = closure; ++ ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ ++ return FFI_OK; ++} ++ ++int ++ffi_closure_UNIX64_inner(ffi_closure *closure, va_list l, void *rp) ++{ ++ ffi_cif *cif; ++ void **avalue; ++ ffi_type **arg_types; ++ long i, avn, argn; ++ ++ cif = closure->cif; ++ avalue = alloca(cif->nargs * sizeof(void *)); ++ ++ argn = 0; ++ ++ i = 0; ++ avn = cif->nargs; ++ arg_types = cif->arg_types; ++ ++ /* Grab the addresses of the arguments from the stack frame. */ ++ while (i < avn) ++ { ++ switch (arg_types[i]->type) ++ { ++ case FFI_TYPE_SINT8: ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_POINTER: ++ { ++ if (l->gp_offset > 48-8) ++ { ++ avalue[i] = l->overflow_arg_area; ++ l->overflow_arg_area = (char *)l->overflow_arg_area + 8; ++ } ++ else ++ { ++ avalue[i] = (char *)l->reg_save_area + l->gp_offset; ++ l->gp_offset += 8; ++ } ++ } ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ /* FIXME */ ++ FFI_ASSERT(0); ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ { ++ if (l->fp_offset > 176-16) ++ { ++ avalue[i] = l->overflow_arg_area; ++ l->overflow_arg_area = (char *)l->overflow_arg_area + 8; ++ } ++ else ++ { ++ avalue[i] = (char *)l->reg_save_area + l->fp_offset; ++ l->fp_offset += 16; ++ } ++ } ++#if DEBUG_FFI ++ fprintf (stderr, "double arg %d = %g\n", i, *(double *)avalue[i]); ++#endif ++ break; ++ ++ case FFI_TYPE_FLOAT: ++ { ++ if (l->fp_offset > 176-16) ++ { ++ avalue[i] = l->overflow_arg_area; ++ l->overflow_arg_area = (char *)l->overflow_arg_area + 8; ++ } ++ else ++ { ++ avalue[i] = (char *)l->reg_save_area + l->fp_offset; ++ l->fp_offset += 16; ++ } ++ } ++#if DEBUG_FFI ++ fprintf (stderr, "float arg %d = %g\n", i, *(float *)avalue[i]); ++#endif ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ } ++ ++ argn += ALIGN(arg_types[i]->size, SIZEOF_ARG) / SIZEOF_ARG; ++ i++; ++ } ++ ++ /* Invoke the closure. */ ++ (closure->fun) (cif, rp, avalue, closure->user_data); ++ ++ /* FIXME: Structs not supported. */ ++ FFI_ASSERT(cif->rtype->type != FFI_TYPE_STRUCT); ++ ++ /* Tell ffi_closure_UNIX64 how to perform return type promotions. */ ++ ++ return cif->rtype->type; ++} ++ ++#endif +--- /dev/null Wed Dec 31 19:00:00 1969 ++++ bridges/source/cpp_uno/gcc3_freebsd_x86-64/abi.hxx Wed Mar 8 03:49:42 2006 +@@ -0,0 +1,75 @@ ++/************************************************************************* ++ * ++ * OpenOffice.org - a multi-platform office productivity suite ++ * ++ * $RCSfile$ ++ * ++ * $Revision$ ++ * ++ * last change: $Author$ $Date$ ++ * ++ * The Contents of this file are made available subject to ++ * the terms of GNU Lesser General Public License Version 2.1. ++ * ++ * ++ * GNU Lesser General Public License Version 2.1 ++ * ============================================= ++ * Copyright 2005 by Sun Microsystems, Inc. ++ * 901 San Antonio Road, Palo Alto, CA 94303, USA ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License version 2.1, as published by the Free Software Foundation. ++ * ++ * This library 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 for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ * ++ ************************************************************************/ ++ ++#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 ); ++ ++/** 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 ); ++ ++void fill_struct( typelib_TypeDescriptionReference *pTypeRef, void * const *pGPR, void * const *pSSE, void *pStruct ); ++ ++} // namespace x86_64 ++ ++#endif // _BRIDGES_CPP_UNO_X86_64_ABI_HXX_ +--- /dev/null Wed Dec 31 19:00:00 1969 ++++ bridges/source/cpp_uno/gcc3_freebsd_x86-64/call.s Mon May 15 13:21:10 2006 +@@ -0,0 +1,93 @@ ++ .text ++ .align 2 ++.globl privateSnippetExecutor ++ .type privateSnippetExecutor, @function ++privateSnippetExecutor: ++.LFB3: ++ pushq %rbp ++.LCFI0: ++ movq %rsp, %rbp ++.LCFI1: ++ subq $160, %rsp ++.LCFI2: ++ 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) ++ jmp .Lfinish ++.Lfloat: ++ movlpd -144(%rbp), %xmm0 # Return value (float/double case) ++ ++.Lfinish: ++ leave ++ ret ++.LFE3: ++ .size privateSnippetExecutor, .-privateSnippetExecutor ++ .section .eh_frame,"a",@progbits ++.Lframe1: ++ .long .LECIE1-.LSCIE1 ++.LSCIE1: ++ .long 0x0 ++ .byte 0x1 ++ .string "zR" ++ .uleb128 0x1 ++ .sleb128 -8 ++ .byte 0x10 ++ .uleb128 0x1 ++ .byte 0x1b ++ .byte 0xc ++ .uleb128 0x7 ++ .uleb128 0x8 ++ .byte 0x90 ++ .uleb128 0x1 ++ .align 8 ++.LECIE1: ++.LSFDE1: ++ .long .LEFDE1-.LASFDE1 ++.LASFDE1: ++ .long .LASFDE1-.Lframe1 ++ .long .LFB3-. ++ .long .LFE3-.LFB3 ++ .uleb128 0x0 ++ .byte 0x4 ++ .long .LCFI0-.LFB3 ++ .byte 0xe ++ .uleb128 0x10 ++ .byte 0x86 ++ .uleb128 0x2 ++ .byte 0x4 ++ .long .LCFI1-.LCFI0 ++ .byte 0xd ++ .uleb128 0x6 ++ .align 8 ++.LEFDE1: ++ .section .note.GNU-stack,"",@progbits +--- /dev/null Wed Dec 31 19:00:00 1969 ++++ bridges/source/cpp_uno/gcc3_freebsd_x86-64/cpp2uno.cxx Tue May 9 12:49:06 2006 +@@ -0,0 +1,539 @@ ++/************************************************************************* ++ * ++ * OpenOffice.org - a multi-platform office productivity suite ++ * ++ * $RCSfile$ ++ * ++ * $Revision$ ++ * ++ * last change: $Author$ $Date$ ++ * ++ * The Contents of this file are made available subject to ++ * the terms of GNU Lesser General Public License Version 2.1. ++ * ++ * ++ * GNU Lesser General Public License Version 2.1 ++ * ============================================= ++ * Copyright 2005 by Sun Microsystems, Inc. ++ * 901 San Antonio Road, Palo Alto, CA 94303, USA ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License version 2.1, as published by the Free Software Foundation. ++ * ++ * This library 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 for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ * ++ ************************************************************************/ ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <hash_map> ++ ++#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 paramaters 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 */ ) ++{ ++ int nr_gpr = 0; //number of gpr registers used ++ int nr_fpr = 0; //number of fpr regsiters 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]; ++ typelib_TypeDescription * pParamTypeDescr = 0; ++ TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); ++ ++ int nUsedGPR = 0; ++ int nUsedSSE = 0; ++ bool bFitsRegisters = x86_64::examine_argument( rParam.pTypeRef, false, nUsedGPR, nUsedSSE ); ++ if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ) ) // 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++; ++ } ++ ++ // no longer needed ++ TYPELIB_DANGER_RELEASE( pParamTypeDescr ); ++ } ++ else // struct <= 16 bytes || ptr to complex value || ref ++ { ++ void *pCppStack; ++ char pTmpStruct[16]; ++ ++ if ( bFitsRegisters && !rParam.bOut && ++ ( pParamTypeDescr->eTypeClass == typelib_TypeClass_STRUCT || ++ pParamTypeDescr->eTypeClass == typelib_TypeClass_EXCEPTION ) ) ++ { ++ if ( ( nr_gpr + nUsedGPR <= x86_64::MAX_GPR_REGS ) && ( nr_fpr + nUsedSSE <= x86_64::MAX_SSE_REGS ) ) ++ { ++ x86_64::fill_struct( rParam.pTypeRef, gpreg, fpreg, pTmpStruct ); ++#if OSL_DEBUG_LEVEL > 1 ++ fprintf( stderr, "nUsedGPR == %d, nUsedSSE == %d, pTmpStruct[0] == 0x%x, pTmpStruct[1] == 0x%x, **gpreg == 0x%lx\n", ++ nUsedGPR, nUsedSSE, pTmpStruct[0], pTmpStruct[1], *(sal_uInt64*)*gpreg ); ++#endif ++ ++ pCppArgs[nPos] = pCppStack = reinterpret_cast<void *>( pTmpStruct ); ++ gpreg += nUsedGPR; ++ fpreg += nUsedSSE; ++ } ++ else ++ pCppArgs[nPos] = pCppStack = *ovrflw++; ++ } ++ else 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 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 ++ // is here for dummy ++ return typelib_TypeClass_VOID; ++ } ++ 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 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::createFromAscii("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::createFromAscii("no member description found!"), ++ reinterpret_cast<XInterface *>( pCppI ) ); ++ // is here for dummy ++ eRet = typelib_TypeClass_VOID; ++ } ++ } ++ ++ 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; ++ ++ return code + codeSnippetSize; ++} ++ ++//================================================================================================== ++void ** bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable( void * block ) ++{ ++ return static_cast<void **>( block ) + 2; ++} ++ ++//================================================================================================== ++sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( ++ sal_Int32 slotCount) ++{ ++ return ( slotCount + 2 ) * sizeof( void * ) + slotCount * codeSnippetSize; ++} ++ ++//================================================================================================== ++void ** bridges::cpp_uno::shared::VtableFactory::initializeBlock( void * block ) ++{ ++ void ** slots = mapBlockToVtable( block ); ++ slots[-2] = 0; ++ slots[-1] = 0; ++ ++ return slots; ++} ++ ++//================================================================================================== ++ ++unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( ++ void ** slots, unsigned char * code, ++ typelib_InterfaceTypeDescription const * type, sal_Int32 nFunctionOffset, ++ sal_Int32 functionCount, sal_Int32 nVtableOffset ) ++{ ++ 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 ++ *slots++ = code; ++ code = codeSnippet( code, nFunctionOffset++, nVtableOffset, ++ x86_64::return_in_hidden_param( pAttrTD->pAttributeTypeRef ) ); ++ ++ if ( ! pAttrTD->bReadOnly ) ++ { ++ // set method ++ *slots++ = code; ++ code = codeSnippet( code, nFunctionOffset++, nVtableOffset, false ); ++ } ++ } ++ else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass ) ++ { ++ typelib_InterfaceMethodTypeDescription *pMethodTD = ++ reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD ); ++ ++ *slots++ = code; ++ 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( ++ unsigned char const *, unsigned char const * ) ++{ ++} +--- /dev/null Wed Dec 31 19:00:00 1969 ++++ bridges/source/cpp_uno/gcc3_freebsd_x86-64/except.cxx Mon May 8 17:19:14 2006 +@@ -0,0 +1,334 @@ ++/************************************************************************* ++ * ++ * OpenOffice.org - a multi-platform office productivity suite ++ * ++ * $RCSfile$ ++ * ++ * $Revision$ ++ * ++ * last change: $Author$ $Date$ ++ * ++ * The Contents of this file are made available subject to ++ * the terms of GNU Lesser General Public License Version 2.1. ++ * ++ * ++ * GNU Lesser General Public License Version 2.1 ++ * ============================================= ++ * Copyright 2005 by Sun Microsystems, Inc. ++ * 901 San Antonio Road, Palo Alto, CA 94303, USA ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License version 2.1, as published by the Free Software Foundation. ++ * ++ * This library 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 for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ * ++ ************************************************************************/ ++ ++#include <stdio.h> ++#include <dlfcn.h> ++#include <cxxabi.h> ++#include <hash_map> ++ ++#include <rtl/strbuf.hxx> ++#include <rtl/ustrbuf.hxx> ++#include <osl/diagnose.h> ++#include <osl/mutex.hxx> ++ ++#include <com/sun/star/uno/genfunc.hxx> ++#include "com/sun/star/uno/RuntimeException.hpp" ++#include <typelib/typedescription.hxx> ++#include <uno/any2.h> ++ ++#include "share.hxx" ++ ++ ++using namespace ::std; ++using namespace ::osl; ++using namespace ::rtl; ++using namespace ::com::sun::star::uno; ++using namespace ::__cxxabiv1; ++ ++ ++namespace CPPU_CURRENT_NAMESPACE ++{ ++ ++void dummy_can_throw_anything( char const * ) ++{ ++} ++ ++//================================================================================================== ++static OUString toUNOname( char const * p ) SAL_THROW( () ) ++{ ++#if OSL_DEBUG_LEVEL > 1 ++ char const * start = p; ++#endif ++ ++ // example: N3com3sun4star4lang24IllegalArgumentExceptionE ++ ++ OUStringBuffer buf( 64 ); ++ OSL_ASSERT( 'N' == *p ); ++ ++p; // skip N ++ ++ while ('E' != *p) ++ { ++ // read chars count ++ long n = (*p++ - '0'); ++ while ('0' <= *p && '9' >= *p) ++ { ++ n *= 10; ++ n += (*p++ - '0'); ++ } ++ buf.appendAscii( p, n ); ++ p += n; ++ if ('E' != *p) ++ buf.append( (sal_Unicode)'.' ); ++ } ++ ++#if OSL_DEBUG_LEVEL > 1 ++ OUString ret( buf.makeStringAndClear() ); ++ OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); ++ fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); ++ return ret; ++#else ++ return buf.makeStringAndClear(); ++#endif ++} ++ ++//================================================================================================== ++class RTTI ++{ ++ typedef hash_map< OUString, type_info *, OUStringHash > t_rtti_map; ++ ++ Mutex m_mutex; ++ t_rtti_map m_rttis; ++ t_rtti_map m_generatedRttis; ++ ++ void * m_hApp; ++ ++public: ++ RTTI() SAL_THROW( () ); ++ ~RTTI() SAL_THROW( () ); ++ ++ type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () ); ++}; ++//__________________________________________________________________________________________________ ++RTTI::RTTI() SAL_THROW( () ) ++ : m_hApp( dlopen( 0, RTLD_NOW | RTLD_GLOBAL ) ) ++{ ++} ++//__________________________________________________________________________________________________ ++RTTI::~RTTI() SAL_THROW( () ) ++{ ++ dlclose( m_hApp ); ++} ++ ++//__________________________________________________________________________________________________ ++type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () ) ++{ ++ type_info * rtti; ++ ++ OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; ++ ++ MutexGuard guard( m_mutex ); ++ t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) ); ++ if (iFind == m_rttis.end()) ++ { ++ // RTTI symbol ++ OStringBuffer buf( 64 ); ++ buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") ); ++ sal_Int32 index = 0; ++ do ++ { ++ OUString token( unoName.getToken( 0, '.', index ) ); ++ buf.append( token.getLength() ); ++ OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); ++ buf.append( c_token ); ++ } ++ while (index >= 0); ++ buf.append( 'E' ); ++ ++ OString symName( buf.makeStringAndClear() ); ++ rtti = (type_info *)dlsym( RTLD_DEFAULT, symName.getStr() ); ++ ++ if (rtti) ++ { ++ pair< t_rtti_map::iterator, bool > insertion( ++ m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); ++ OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" ); ++ } ++ else ++ { ++ // try to lookup the symbol in the generated rtti map ++ t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) ); ++ if (iFind == m_generatedRttis.end()) ++ { ++ // we must generate it ! ++ // symbol and rtti-name is nearly identical, ++ // the symbol is prefixed with _ZTI ++ char const * rttiName = symName.getStr() +4; ++#if OSL_DEBUG_LEVEL > 1 ++ fprintf( stderr,"generated rtti for %s\n", rttiName ); ++#endif ++ if (pTypeDescr->pBaseTypeDescription) ++ { ++ // ensure availability of base ++ type_info * base_rtti = getRTTI( ++ (typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription ); ++ rtti = new __si_class_type_info( ++ strdup( rttiName ), (__class_type_info *)base_rtti ); ++ } ++ else ++ { ++ // this class has no base class ++ rtti = new __class_type_info( strdup( rttiName ) ); ++ } ++ ++ pair< t_rtti_map::iterator, bool > insertion( ++ m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); ++ OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" ); ++ } ++ else // taking already generated rtti ++ { ++ rtti = iFind->second; ++ } ++ } ++ } ++ else ++ { ++ rtti = iFind->second; ++ } ++ ++ return rtti; ++} ++ ++//-------------------------------------------------------------------------------------------------- ++static void deleteException( void * pExc ) ++{ ++ __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); ++ typelib_TypeDescription * pTD = 0; ++ OUString unoName( toUNOname( header->exceptionType->name() ) ); ++ ::typelib_typedescription_getByName( &pTD, unoName.pData ); ++ OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" ); ++ if (pTD) ++ { ++ ::uno_destructData( pExc, pTD, cpp_release ); ++ ::typelib_typedescription_release( pTD ); ++ } ++} ++ ++//================================================================================================== ++void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) ++{ ++#if OSL_DEBUG_LEVEL > 1 ++ OString cstr( ++ OUStringToOString( ++ *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), ++ RTL_TEXTENCODING_ASCII_US ) ); ++ fprintf( stderr, "> uno exception occured: %s\n", cstr.getStr() ); ++#endif ++ void * pCppExc; ++ type_info * rtti; ++ ++ { ++ // construct cpp exception object ++ typelib_TypeDescription * pTypeDescr = 0; ++ TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); ++ OSL_ASSERT( pTypeDescr ); ++ if (! pTypeDescr) ++ { ++ throw RuntimeException( ++ OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) + ++ *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), ++ Reference< XInterface >() ); ++ } ++ ++ pCppExc = __cxa_allocate_exception( pTypeDescr->nSize ); ++ ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); ++ ++ // destruct uno exception ++ ::uno_any_destruct( pUnoExc, 0 ); ++ // avoiding locked counts ++ static RTTI * s_rtti = 0; ++ if (! s_rtti) ++ { ++ MutexGuard guard( Mutex::getGlobalMutex() ); ++ if (! s_rtti) ++ { ++#ifdef LEAK_STATIC_DATA ++ s_rtti = new RTTI(); ++#else ++ static RTTI rtti_data; ++ s_rtti = &rtti_data; ++#endif ++ } ++ } ++ rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr ); ++ TYPELIB_DANGER_RELEASE( pTypeDescr ); ++ OSL_ENSURE( rtti, "### no rtti for throwing exception!" ); ++ if (! rtti) ++ { ++ throw RuntimeException( ++ OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) + ++ *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), ++ Reference< XInterface >() ); ++ } ++ } ++ ++ __cxa_throw( pCppExc, rtti, deleteException ); ++} ++ ++//================================================================================================== ++void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) ++{ ++ if (! header) ++ { ++ RuntimeException aRE( ++ OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ), ++ Reference< XInterface >() ); ++ Type const & rType = ::getCppuType( &aRE ); ++ uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); ++#if OSL_DEBUG_LEVEL > 0 ++ OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); ++ OSL_ENSURE( 0, 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 occured: %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_ENSURE( 0, cstr.getStr() ); ++#endif ++ } ++ else ++ { ++ // construct uno exception any ++ uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); ++ typelib_typedescription_release( pExcTypeDescr ); ++ } ++} ++ ++} ++ +--- /dev/null Wed Dec 31 19:00:00 1969 ++++ bridges/source/cpp_uno/gcc3_freebsd_x86-64/makefile.mk Mon May 8 17:17:43 2006 +@@ -0,0 +1,92 @@ ++#************************************************************************* ++# ++# OpenOffice.org - a multi-platform office productivity suite ++# ++# $RCSfile$ ++# ++# $Revision$ ++# ++# last change: $Author$ $Date$ ++# ++# The Contents of this file are made available subject to ++# the terms of GNU Lesser General Public License Version 2.1. ++# ++# ++# GNU Lesser General Public License Version 2.1 ++# ============================================= ++# Copyright 2005 by Sun Microsystems, Inc. ++# 901 San Antonio Road, Palo Alto, CA 94303, USA ++# ++# This library is free software; you can redistribute it and/or ++# modify it under the terms of the GNU Lesser General Public ++# License version 2.1, as published by the Free Software Foundation. ++# ++# This library 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 for more details. ++# ++# You should have received a copy of the GNU Lesser General Public ++# License along with this library; if not, write to the Free Software ++# Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++# MA 02111-1307 USA ++# ++#************************************************************************* ++ ++PRJ=..$/..$/.. ++ ++PRJNAME=bridges ++TARGET=gcc3_uno ++LIBTARGET=no ++ENABLE_EXCEPTIONS=TRUE ++NO_BSYMBOLIC=TRUE ++ ++# --- Settings ----------------------------------------------------- ++ ++.INCLUDE : svpre.mk ++.INCLUDE : settings.mk ++.INCLUDE : sv.mk ++ ++# --- Files -------------------------------------------------------- ++ ++.IF "$(COM)$(OS)$(CPU)$(COMNAME)" == "GCCFREEBSDXgcc3" ++ ++.IF "$(cppu_no_leak)" == "" ++CFLAGS += -DLEAK_STATIC_DATA ++.ENDIF ++ ++NOOPTFILES= \ ++ $(SLO)$/uno2cpp.obj ++ ++ ++CFLAGSNOOPT=-O0 ++ ++SLOFILES= \ ++ $(SLO)$/abi.obj \ ++ $(SLO)$/except.obj \ ++ $(SLO)$/cpp2uno.obj \ ++ $(SLO)$/uno2cpp.obj \ ++ $(SLO)$/call.obj ++ ++SHL1TARGET= $(TARGET) ++ ++SHL1DEF=$(MISC)$/$(SHL1TARGET).def ++SHL1IMPLIB=i$(TARGET) ++SHL1VERSIONMAP=..$/..$/bridge_exports.map ++ ++SHL1OBJS = $(SLOFILES) ++SHL1LIBS = $(SLB)$/cpp_uno_shared.lib ++ ++SHL1STDLIBS= \ ++ $(CPPULIB) \ ++ $(SALLIB) ++ ++.ENDIF ++ ++# --- Targets ------------------------------------------------------ ++ ++.INCLUDE : target.mk ++ ++$(SLO)$/%.obj: %.s ++ $(CC) -c -o $(SLO)$/$(@:b).o $< ++ touch $@ +--- /dev/null Wed Dec 31 19:00:00 1969 ++++ bridges/source/cpp_uno/gcc3_freebsd_x86-64/share.hxx Wed Mar 8 03:51:06 2006 +@@ -0,0 +1,98 @@ ++/************************************************************************* ++ * ++ * OpenOffice.org - a multi-platform office productivity suite ++ * ++ * $RCSfile$ ++ * ++ * $Revision$ ++ * ++ * last change: $Author$ $Date$ ++ * ++ * The Contents of this file are made available subject to ++ * the terms of GNU Lesser General Public License Version 2.1. ++ * ++ * ++ * GNU Lesser General Public License Version 2.1 ++ * ============================================= ++ * Copyright 2005 by Sun Microsystems, Inc. ++ * 901 San Antonio Road, Palo Alto, CA 94303, USA ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License version 2.1, as published by the Free Software Foundation. ++ * ++ * This library 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 for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ * ++ ************************************************************************/ ++ ++#include "uno/mapping.h" ++ ++#include <typeinfo> ++#include <exception> ++#include <cstddef> ++ ++namespace CPPU_CURRENT_NAMESPACE ++{ ++ ++void dummy_can_throw_anything( char const * ); ++ ++// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h ++ ++struct _Unwind_Exception ++{ ++ unsigned exception_class __attribute__((__mode__(__DI__))); ++ void * exception_cleanup; ++ unsigned private_1 __attribute__((__mode__(__word__))); ++ unsigned private_2 __attribute__((__mode__(__word__))); ++} __attribute__((__aligned__)); ++ ++struct __cxa_exception ++{ ++ ::std::type_info *exceptionType; ++ void (*exceptionDestructor)(void *); ++ ++ ::std::unexpected_handler unexpectedHandler; ++ ::std::terminate_handler terminateHandler; ++ ++ __cxa_exception *nextException; ++ ++ int handlerCount; ++ ++ int handlerSwitchValue; ++ const unsigned char *actionRecord; ++ const unsigned char *languageSpecificData; ++ void *catchTemp; ++ void *adjustedPtr; ++ ++ _Unwind_Exception unwindHeader; ++}; ++ ++extern "C" void *__cxa_allocate_exception( ++ std::size_t thrown_size ) throw(); ++extern "C" void __cxa_throw ( ++ void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn)); ++ ++struct __cxa_eh_globals ++{ ++ __cxa_exception *caughtExceptions; ++ unsigned int uncaughtExceptions; ++}; ++extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); ++ ++// ----- ++ ++//================================================================================================== ++void raiseException( ++ uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); ++//================================================================================================== ++void fillUnoException( ++ __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); ++} +--- /dev/null Wed Dec 31 19:00:00 1969 ++++ bridges/source/cpp_uno/gcc3_freebsd_x86-64/uno2cpp.cxx Wed Mar 8 03:51:19 2006 +@@ -0,0 +1,645 @@ ++/************************************************************************* ++ * ++ * OpenOffice.org - a multi-platform office productivity suite ++ * ++ * $RCSfile$ ++ * ++ * $Revision$ ++ * ++ * last change: $Author$ $Date$ ++ * ++ * The Contents of this file are made available subject to ++ * the terms of GNU Lesser General Public License Version 2.1. ++ * ++ * ++ * GNU Lesser General Public License Version 2.1 ++ * ============================================= ++ * Copyright 2005 by Sun Microsystems, Inc. ++ * 901 San Antonio Road, Palo Alto, CA 94303, USA ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License version 2.1, as published by the Free Software Foundation. ++ * ++ * This library 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 for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ * ++ ************************************************************************/ ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <rtl/alloc.h> ++ ++#include <com/sun/star/uno/genfunc.hxx> ++#include "com/sun/star/uno/RuntimeException.hpp" ++#include <uno/data.h> ++ ++#include <bridges/cpp_uno/shared/bridge.hxx> ++#include <bridges/cpp_uno/shared/types.hxx> ++#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" ++#include "bridges/cpp_uno/shared/vtables.hxx" ++ ++#include "share.hxx" ++ ++using namespace ::rtl; ++using namespace ::com::sun::star::uno; ++ ++void dummy_can_throw_anything( char const * ); ++ ++// 6 integral parameters are passed in registers ++const sal_uInt32 GPR_COUNT = 6; ++ ++// 8 floating point parameters are passed in SSE registers ++const sal_uInt32 FPR_COUNT = 8; ++ ++static inline void ++invoke_count_words(char * pPT, // Parameter Types ++ sal_uInt32 & nr_gpr, // Number of arguments in GPRs ++ sal_uInt32 & nr_fpr, // Number of arguments in FPRs ++ sal_uInt32 & nr_stack) // Number of arguments in stack ++{ ++ nr_gpr = 0; ++ nr_fpr = 0; ++ nr_stack = 0; ++ char c; ++ ++ while ((c = *pPT++) != 'X') ++ { ++ if (c == 'F' || c == 'D') ++ { ++ if (nr_fpr < FPR_COUNT) ++ nr_fpr++; ++ else ++ nr_stack++; ++ } ++ else ++ { ++ if (nr_gpr < GPR_COUNT) ++ nr_gpr++; ++ else ++ nr_stack++; ++ } ++ } ++} ++ ++static void ++invoke_copy_to_stack(sal_uInt64 * pDS, // Stack Storage ++ char * pPT, // Parameter Types ++ sal_uInt64 * pSV, // Source Values ++ sal_uInt64 * pGPR, // General Purpose Registers ++ double * pFPR) // Floating-Point Registers ++{ ++ sal_uInt32 nr_gpr = 0; ++ sal_uInt32 nr_fpr = 0; ++ sal_uInt64 value; ++ char c; ++ ++ while ((c = *pPT++) != 'X') ++ { ++ switch (c) ++ { ++ case 'D': // Double ++ if (nr_fpr < FPR_COUNT) ++ pFPR[nr_fpr++] = *reinterpret_cast<double *>( pSV++ ); ++ else ++ *pDS++ = *pSV++; ++ break; ++ ++ case 'F': // Float ++ if (nr_fpr < FPR_COUNT) ++ // The value in %xmm register is already prepared to ++ // be retrieved as a float. Therefore, we pass the ++ // value verbatim, as a double without conversion. ++ pFPR[nr_fpr++] = *reinterpret_cast<double *>( pSV++ ); ++ else ++ *pDS++ = *reinterpret_cast<double *>( pSV++ ); ++ break; ++ ++ case 'H': // 64-bit Word ++ if (nr_gpr < GPR_COUNT) ++ pGPR[nr_gpr++] = *pSV++; ++ else ++ *pDS++ = *pSV++; ++ break; ++ ++ case 'I': // 32-bit Word ++ if (nr_gpr < GPR_COUNT) ++ pGPR[nr_gpr++] = *reinterpret_cast<sal_uInt32 *>( pSV++ ); ++ else ++ *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV++ ); ++ break; ++ ++ case 'S': // 16-bit Word ++ if (nr_gpr < GPR_COUNT) ++ pGPR[nr_gpr++] = *reinterpret_cast<sal_uInt16 *>( pSV++ ); ++ else ++ *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV++ ); ++ break; ++ ++ case 'B': // Byte ++ if (nr_gpr < GPR_COUNT) ++ pGPR[nr_gpr++] = *reinterpret_cast<sal_uInt8 *>( pSV++ ); ++ else ++ *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV++ ); ++ break; ++ ++ default: // Default, assume 64-bit values ++ if (nr_gpr < GPR_COUNT) ++ pGPR[nr_gpr++] = *pSV++; ++ else ++ *pDS++ = *pSV++; ++ break; ++ } ++ } ++} ++ ++//================================================================================================== ++static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex, ++ void * pRegisterReturn, typelib_TypeClass eReturnType, ++ char * pPT, sal_uInt64 * pStackLongs, sal_uInt32 nStackLongs) ++{ ++ sal_uInt32 nr_gpr, nr_fpr, nr_stack; ++ invoke_count_words(pPT, nr_gpr, nr_fpr, nr_stack); ++ ++ // Stack, if used, must be 16-bytes aligned ++ if (nr_stack) ++ nr_stack = (nr_stack + 1) & ~1; ++ ++ bool bReturnsSimpleType = bridges::cpp_uno::shared::isSimpleType( eReturnType ); ++ ++#if OSL_DEBUG_LEVEL > 1 ++ // Let's figure out what is really going on here ++ fprintf(stderr,"callVirtualMethod() parameters string is %s\n", pPT); ++ { ++ sal_uInt32 k = nStackLongs; ++ sal_uInt64 *q = pStackLongs; ++ while (k > 0) ++ { ++ fprintf(stderr, "uno stack is: %lx\n", *q); ++ k--; ++ q++; ++ } ++ } ++#endif ++ ++ // Load parameters to stack, if necessary ++ sal_uInt64 *stack = (sal_uInt64 *) __builtin_alloca(nr_stack * 8); ++ sal_uInt64 gpregs[GPR_COUNT]; ++ double fpregs[FPR_COUNT]; ++ invoke_copy_to_stack(stack, pPT, pStackLongs, gpregs, fpregs); ++ ++ // Load FPR registers from fpregs[] ++ register double d0 asm("xmm0"); ++ register double d1 asm("xmm1"); ++ register double d2 asm("xmm2"); ++ register double d3 asm("xmm3"); ++ register double d4 asm("xmm4"); ++ register double d5 asm("xmm5"); ++ register double d6 asm("xmm6"); ++ register double d7 asm("xmm7"); ++ ++ switch (nr_fpr) { ++#define ARG_FPR(N) \ ++ case N+1: d##N = fpregs[N]; ++ ARG_FPR(7); ++ ARG_FPR(6); ++ ARG_FPR(5); ++ ARG_FPR(4); ++ ARG_FPR(3); ++ ARG_FPR(2); ++ ARG_FPR(1); ++ ARG_FPR(0); ++ case 0:; ++#undef ARG_FPR ++ } ++ ++ // Load GPR registers from gpregs[] ++ register sal_uInt64 a0 asm("rdi"); ++ register sal_uInt64 a1 asm("rsi"); ++ register sal_uInt64 a2 asm("rdx"); ++ register sal_uInt64 a3 asm("rcx"); ++ register sal_uInt64 a4 asm("r8"); ++ register sal_uInt64 a5 asm("r9"); ++ ++ switch (nr_gpr) { ++#define ARG_GPR(N) \ ++ case N+1: a##N = gpregs[N]; ++ ARG_GPR(5); ++ ARG_GPR(4); ++ ARG_GPR(3); ++ ARG_GPR(2); ++ ARG_GPR(1); ++ ARG_GPR(0); ++ case 0:; ++#undef ARG_GPR ++ } ++ ++ if ( bReturnsSimpleType ) ++ a0 = (sal_uInt64) pThis; ++ else ++ a1 = (sal_uInt64) pThis; ++ ++ // Ensure that assignments to SSE registers won't be optimized away ++ asm("" :: ++ "x" (d0), "x" (d1), "x" (d2), "x" (d3), ++ "x" (d4), "x" (d5), "x" (d6), "x" (d7)); ++ ++ // Get pointer to method ++ sal_uInt64 pMethod = *((sal_uInt64 *)pThis); ++ pMethod += 8 * nVtableIndex; ++ pMethod = *((sal_uInt64 *)pMethod); ++ ++ union ReturnValue { ++ struct { ++ sal_uInt64 rax; ++ sal_uInt64 rdx; ++ } i; ++ struct { ++ double xmm0; ++ double xmm1; ++ } f; ++ }; ++ ++ typedef ReturnValue (* FunctionCall )( sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64 ); ++ ++ // Perform the call ++ ReturnValue aRet = ( ( FunctionCall ) pMethod )( a0, a1, a2, a3, a4, a5 ); ++ ++ switch (eReturnType) ++ { ++ case typelib_TypeClass_HYPER: ++ case typelib_TypeClass_UNSIGNED_HYPER: ++ *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = aRet.i.rax; ++ break; ++ case typelib_TypeClass_LONG: ++ case typelib_TypeClass_UNSIGNED_LONG: ++ case typelib_TypeClass_ENUM: ++ *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt32*>( &aRet.i.rax ); ++ break; ++ case typelib_TypeClass_CHAR: ++ case typelib_TypeClass_SHORT: ++ case typelib_TypeClass_UNSIGNED_SHORT: ++ *reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt16*>( &aRet.i.rax ); ++ break; ++ case typelib_TypeClass_BOOLEAN: ++ case typelib_TypeClass_BYTE: ++ *reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt8*>( &aRet.i.rax ); ++ break; ++ case typelib_TypeClass_FLOAT: ++ *reinterpret_cast<float *>( pRegisterReturn ) = *reinterpret_cast<float*>( &aRet.f.xmm0 ); ++ break; ++ case typelib_TypeClass_DOUBLE: ++ *reinterpret_cast<double *>( pRegisterReturn ) = *reinterpret_cast<double*>( &aRet.f.xmm0 ); ++ break; ++ } ++} ++ ++ ++//================================================================================================== ++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 ... ++ char * pCppStack = (char *)__builtin_alloca( (nParams + 3) * sizeof(sal_uInt64) ); ++ char * pCppStackStart = pCppStack; ++ ++ // We need to know parameter types for callVirtualMethod() so generate a signature string ++ char * pParamType = (char *)__builtin_alloca( nParams + 3 ); ++ char * pPT = pParamType; ++ ++ // 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 ++ ++ if (pReturnTypeDescr) ++ { ++ if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) ++ { ++ pCppReturn = pUnoReturn; // direct way for simple types ++ } ++ else ++ { ++ // complex return via ptr ++ pCppReturn = *(void **)pCppStack = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) ++ ? __builtin_alloca( pReturnTypeDescr->nSize ) ++ : pUnoReturn); // direct way ++ *pPT++ = 'H'; ++ pCppStack += sizeof(void *); ++ } ++ } ++ ++ // Push "this" pointer ++ void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset; ++ *(void **)pCppStack = pAdjustedThisPtr; ++ *pPT++ = 'H'; ++ pCppStack += sizeof(void *); ++ ++ // stack space ++ // Args ++ void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); ++ // Indizes of values this have to be converted (interface conversion cpp<=>uno) ++ sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); ++ // Type descriptions for reconversions ++ typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); ++ ++ sal_Int32 nTempIndizes = 0; ++ ++ for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) ++ { ++ const typelib_MethodParameter & rParam = pParams[nPos]; ++ typelib_TypeDescription * pParamTypeDescr = 0; ++ TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); ++ ++ if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) ++ { ++ uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr, ++ pThis->getBridge()->getUno2Cpp() ); ++ ++ switch (pParamTypeDescr->eTypeClass) ++ { ++ ++ // we need to know type of each param so that we know whether to use ++ // gpr or fpr to pass in parameters: ++ // Key: I - 32-bit value passed in gpr ++ // B - byte value passed in gpr ++ // S - short value passed in gpr ++ // F - float value pass in fpr ++ // D - double value pass in fpr ++ // H - long value passed in gpr ++ // X - indicates end of parameter description string ++ ++ case typelib_TypeClass_LONG: ++ case typelib_TypeClass_UNSIGNED_LONG: ++ case typelib_TypeClass_ENUM: ++ *pPT++ = 'I'; ++ break; ++ case typelib_TypeClass_SHORT: ++ case typelib_TypeClass_CHAR: ++ case typelib_TypeClass_UNSIGNED_SHORT: ++ *pPT++ = 'S'; ++ break; ++ case typelib_TypeClass_BOOLEAN: ++ case typelib_TypeClass_BYTE: ++ *pPT++ = 'B'; ++ break; ++ case typelib_TypeClass_FLOAT: ++ *pPT++ = 'F'; ++ break; ++ case typelib_TypeClass_DOUBLE: ++ *pPT++ = 'D'; ++ break; ++ case typelib_TypeClass_HYPER: ++ case typelib_TypeClass_UNSIGNED_HYPER: ++ *pPT++ = 'H'; ++ break; ++ } ++ ++ // no longer needed ++ TYPELIB_DANGER_RELEASE( pParamTypeDescr ); ++ } ++ else // ptr to complex value | ref ++ { ++ if (! rParam.bIn) // is pure out ++ { ++ // cpp out is constructed mem, uno out is not! ++ uno_constructData( ++ *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), ++ pParamTypeDescr ); ++ pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call ++ // will be released at reconversion ++ ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; ++ } ++ // is in/inout ++ else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) ++ { ++ uno_copyAndConvertData( ++ *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), ++ pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); ++ ++ pTempIndizes[nTempIndizes] = nPos; // has to be reconverted ++ // will be released at reconversion ++ ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; ++ } ++ else // direct way ++ { ++ *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; ++ // no longer needed ++ TYPELIB_DANGER_RELEASE( pParamTypeDescr ); ++ } ++ // FIXME: is this the right way to pass these? ++ *pPT++='H'; ++ } ++ pCppStack += sizeof(sal_uInt64); // standard parameter length ++ } ++ ++ // terminate the signature string ++ *pPT++ = 'X'; ++ *pPT = 0; ++ ++ try ++ { ++ OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 7), "UNALIGNED STACK !!! (Please DO panic)" ); ++ callVirtualMethod( ++ pAdjustedThisPtr, aVtableSlot.index, ++ pCppReturn, pReturnTypeDescr->eTypeClass, pParamType, ++ (sal_uInt64 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_uInt64) ); ++ // NO exception occured... ++ *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( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); ++ ++ // temporary params ++ for ( ; nTempIndizes--; ) ++ { ++ sal_Int32 nIndex = pTempIndizes[nTempIndizes]; ++ // destroy temp cpp param => cpp: every param was constructed ++ uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); ++ TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); ++ } ++ // return type ++ if (pReturnTypeDescr) ++ TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); ++ } ++} ++ ++ ++//================================================================================================== ++void bridges::cpp_uno::shared::UnoInterfaceProxy::dispatch( ++ uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, ++ void * pReturn, void * pArgs[], uno_Any ** ppException ) SAL_THROW(()) ++{ ++ // is my surrogate ++ bridges::cpp_uno::shared::UnoInterfaceProxy * pThis ++ = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); ++ typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; ++ ++ switch (pMemberDescr->eTypeClass) ++ { ++ case typelib_TypeClass_INTERFACE_ATTRIBUTE: ++ { ++ // determine vtable call index ++ sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; ++ OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); ++ ++ 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: ++ { ++ // determine vtable call index ++ sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; ++ OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); ++ ++ 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 ); ++ } ++ } ++} |