bridges: Add support for linux mips64.
Change-Id: I71fd2f7d8bfd1b1511dec91f23b61b9f55d21472 Reviewed-on: https://gerrit.libreoffice.org/16845 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Stephan Bergmann <sbergman@redhat.com> Tested-by: Stephan Bergmann <sbergman@redhat.com>
This commit is contained in:
parent
83b53164b0
commit
55b09bd09d
@ -99,6 +99,15 @@ bridge_noopt_objects := cpp2uno uno2cpp
|
||||
bridge_exception_objects := except
|
||||
endif
|
||||
|
||||
else ifeq ($(CPUNAME),GODSON64)
|
||||
|
||||
ifneq ($(filter ANDROID LINUX,$(OS)),)
|
||||
bridges_SELECTED_BRIDGE := gcc3_linux_mips64
|
||||
bridge_asm_objects := call
|
||||
bridge_noopt_objects := cpp2uno uno2cpp
|
||||
bridge_exception_objects := except
|
||||
endif
|
||||
|
||||
else ifeq ($(OS)-$(CPUNAME),LINUX-POWERPC)
|
||||
|
||||
bridges_SELECTED_BRIDGE := gcc3_linux_powerpc
|
||||
|
38
bridges/source/cpp_uno/gcc3_linux_mips64/call.hxx
Normal file
38
bridges/source/cpp_uno/gcc3_linux_mips64/call.hxx
Normal file
@ -0,0 +1,38 @@
|
||||
/* -*- 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 .
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_GCC3_LINUX_MIPS64_CALL_HXX
|
||||
#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_GCC3_LINUX_MIPS64_CALL_HXX
|
||||
|
||||
#include <sal/config.h>
|
||||
|
||||
#include <sal/types.h>
|
||||
|
||||
namespace {
|
||||
|
||||
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 */ );
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
132
bridges/source/cpp_uno/gcc3_linux_mips64/call.s
Normal file
132
bridges/source/cpp_uno/gcc3_linux_mips64/call.s
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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
|
||||
.globl privateSnippetExecutor
|
||||
.LFB0 = .
|
||||
.cfi_startproc
|
||||
.cfi_personality 0x80,DW.ref.__gxx_personality_v0
|
||||
.cfi_lsda 0,.LLSDA0
|
||||
.ent privateSnippetExecutor
|
||||
.type privateSnippetExecutor, @function
|
||||
privateSnippetExecutor:
|
||||
.set noreorder
|
||||
daddiu $sp,$sp,-160
|
||||
.cfi_def_cfa_offset 160
|
||||
sd $ra,152($sp)
|
||||
.cfi_offset 31, -8
|
||||
.LEHB0 = .
|
||||
// Save the float point registers
|
||||
sdc1 $f12,80($sp)
|
||||
sdc1 $f13,88($sp)
|
||||
sdc1 $f14,96($sp)
|
||||
sdc1 $f15,104($sp)
|
||||
sdc1 $f16,112($sp)
|
||||
sdc1 $f17,120($sp)
|
||||
sdc1 $f18,128($sp)
|
||||
sdc1 $f19,136($sp)
|
||||
// Save the general purpose registers
|
||||
sd $a0,16($sp)
|
||||
sd $a1,24($sp)
|
||||
sd $a2,32($sp)
|
||||
sd $a3,40($sp)
|
||||
sd $a4,48($sp)
|
||||
sd $a5,56($sp)
|
||||
sd $a6,64($sp)
|
||||
sd $a7,72($sp)
|
||||
// Load arguemtns
|
||||
// a0=index
|
||||
move $a0,$v0
|
||||
// a1=offset
|
||||
move $a1,$v1
|
||||
// a2=gpregptr
|
||||
daddiu $a2,$sp,16
|
||||
// a3=fpregptr
|
||||
daddiu $a3,$sp,80
|
||||
// a4=ovrflw
|
||||
daddiu $a4,$sp,160
|
||||
// Call cpp_vtable_call
|
||||
jalr $t9
|
||||
// a5=retregptr
|
||||
move $a5,$sp
|
||||
|
||||
.LEHE0 = .
|
||||
// Perform return value
|
||||
li $v1,10
|
||||
beq $v0,$v1,.Lfloat
|
||||
li $v1,11
|
||||
beq $v0,$v1,.Lfloat
|
||||
ldc1 $f0,0($sp)
|
||||
ldc1 $f2,8($sp)
|
||||
ld $v0,0($sp)
|
||||
b .Lfinish
|
||||
ld $v1,8($sp)
|
||||
.Lfloat:
|
||||
ldc1 $f0,0($sp)
|
||||
ldc1 $f2,8($sp)
|
||||
|
||||
.Lfinish:
|
||||
ld $ra,152($sp)
|
||||
jr $ra
|
||||
daddiu $sp,$sp,160
|
||||
|
||||
.set reorder
|
||||
.end privateSnippetExecutor
|
||||
.cfi_endproc
|
||||
.LFE0:
|
||||
.globl __gxx_personality_v0
|
||||
.section .gcc_except_table,"aw",@progbits
|
||||
.align 3
|
||||
.LLSDA0:
|
||||
.byte 0xff
|
||||
.byte 0x80
|
||||
.uleb128 .LLSDATT0-.LLSDATTD0
|
||||
.LLSDATTD0:
|
||||
.byte 0x1
|
||||
.uleb128 .LLSDACSE0-.LLSDACSB0
|
||||
.LLSDACSB0:
|
||||
.uleb128 .LEHB0-.LFB0
|
||||
.uleb128 .LEHE0-.LEHB0
|
||||
.uleb128 0
|
||||
.uleb128 0
|
||||
.LLSDACSE0:
|
||||
.byte 0x7f
|
||||
.byte 0
|
||||
.align 3
|
||||
.8byte DW.ref._ZTIi
|
||||
.LLSDATT0:
|
||||
.byte 0x1
|
||||
.byte 0
|
||||
.text
|
||||
.size privateSnippetExecutor, .-privateSnippetExecutor
|
||||
.hidden DW.ref._ZTIi
|
||||
.weak DW.ref._ZTIi
|
||||
.section .data.DW.ref._ZTIi,"awG",@progbits,DW.ref._ZTIi,comdat
|
||||
.align 3
|
||||
.type DW.ref._ZTIi, @object
|
||||
.size DW.ref._ZTIi, 8
|
||||
DW.ref._ZTIi:
|
||||
.dword _ZTIi
|
||||
.hidden DW.ref.__gxx_personality_v0
|
||||
.weak DW.ref.__gxx_personality_v0
|
||||
.section .data.DW.ref.__gxx_personality_v0,"awG",@progbits,DW.ref.__gxx_personality_v0,comdat
|
||||
.align 3
|
||||
.type DW.ref.__gxx_personality_v0, @object
|
||||
.size DW.ref.__gxx_personality_v0, 8
|
||||
DW.ref.__gxx_personality_v0:
|
||||
.dword __gxx_personality_v0
|
707
bridges/source/cpp_uno/gcc3_linux_mips64/cpp2uno.cxx
Normal file
707
bridges/source/cpp_uno/gcc3_linux_mips64/cpp2uno.cxx
Normal file
@ -0,0 +1,707 @@
|
||||
/* -*- 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 .
|
||||
*/
|
||||
#include <com/sun/star/uno/genfunc.hxx>
|
||||
#include <sal/log.hxx>
|
||||
#include <typelib/typedescription.hxx>
|
||||
#include <uno/data.h>
|
||||
#include <osl/endian.h>
|
||||
#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 "call.hxx"
|
||||
#include "share.hxx"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace com::sun::star::uno;
|
||||
|
||||
//#define BRDEBUG
|
||||
|
||||
#ifdef BRDEBUG
|
||||
#include <rtl/strbuf.hxx>
|
||||
#include <rtl/ustrbuf.hxx>
|
||||
#include <osl/mutex.hxx>
|
||||
using namespace ::std;
|
||||
using namespace ::osl;
|
||||
using namespace ::rtl;
|
||||
#endif
|
||||
|
||||
#ifndef ANDROID
|
||||
#include <sys/sysmips.h>
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
using namespace ::com::sun::star::uno;
|
||||
|
||||
namespace CPPU_CURRENT_NAMESPACE
|
||||
{
|
||||
bool is_complex_struct(const typelib_TypeDescription * type)
|
||||
{
|
||||
const typelib_CompoundTypeDescription * p
|
||||
= reinterpret_cast< const typelib_CompoundTypeDescription * >(type);
|
||||
for (sal_Int32 i = 0; i < p->nMembers; ++i)
|
||||
{
|
||||
if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT ||
|
||||
p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION)
|
||||
{
|
||||
typelib_TypeDescription * t = 0;
|
||||
TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]);
|
||||
bool b = is_complex_struct(t);
|
||||
TYPELIB_DANGER_RELEASE(t);
|
||||
if (b) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass))
|
||||
return true;
|
||||
}
|
||||
if (p->pBaseTypeDescription != 0)
|
||||
return is_complex_struct(&p->pBaseTypeDescription->aBase);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef )
|
||||
{
|
||||
if (bridges::cpp_uno::shared::isSimpleType(pTypeRef))
|
||||
return false;
|
||||
else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT ||
|
||||
pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
|
||||
{
|
||||
typelib_TypeDescription * pTypeDescr = 0;
|
||||
TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
|
||||
|
||||
//A Composite Type not larger than 16 bytes is returned in up to two GPRs
|
||||
bool bRet = pTypeDescr->nSize > 16 || is_complex_struct(pTypeDescr);
|
||||
|
||||
TYPELIB_DANGER_RELEASE( pTypeDescr );
|
||||
return bRet;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
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 */ )
|
||||
{
|
||||
/* Most MIPS ABIs view the arguments as a struct, of which the
|
||||
first N words go in registers and the rest go on the stack. If I < N, the
|
||||
Ith word might go in Ith integer argument register or the Ith
|
||||
floating-point one. For these ABIs, we only need to remember the number
|
||||
of words passed so far. We are interested only in n64 ABI,so it is the
|
||||
case.
|
||||
*/
|
||||
unsigned int nREG = 0;
|
||||
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp2uno_call:begin\n");
|
||||
#endif
|
||||
|
||||
// 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 (CPPU_CURRENT_NAMESPACE::return_in_hidden_param( pReturnTypeRef ) )
|
||||
{
|
||||
pCppReturn = gpreg[nREG]; // complex return via ptr (pCppReturn)
|
||||
nREG++;
|
||||
|
||||
pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
|
||||
? alloca( pReturnTypeDescr->nSize )
|
||||
: pCppReturn); // direct way
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp2uno_call:complexreturn\n");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
pUnoReturn = pRegisterReturn; // direct way for simple types
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp2uno_call:simplereturn\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// pop this
|
||||
nREG++;
|
||||
|
||||
// stack space
|
||||
static_assert(sizeof(void *) == sizeof(sal_Int64), "### unexpected size!");
|
||||
// parameters
|
||||
void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
|
||||
void ** pCppArgs = pUnoArgs + nParams;
|
||||
// indices of values this have to be converted (interface conversion cpp<=>uno)
|
||||
sal_Int32 * pTempIndices = (sal_Int32 *)(pUnoArgs + (2 * nParams));
|
||||
// type descriptions for reconversions
|
||||
typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
|
||||
|
||||
sal_Int32 nTempIndices = 0;
|
||||
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp2uno_call:nParams=%d\n", nParams);
|
||||
#endif
|
||||
for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
|
||||
{
|
||||
const typelib_MethodParameter & rParam = pParams[nPos];
|
||||
|
||||
typelib_TypeDescription * pParamTypeDescr = 0;
|
||||
TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
|
||||
|
||||
if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) // value
|
||||
{
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp2uno_call:Param %u, type %u\n", nPos, pParamTypeDescr->eTypeClass);
|
||||
#endif
|
||||
switch (pParamTypeDescr->eTypeClass)
|
||||
{
|
||||
case typelib_TypeClass_FLOAT:
|
||||
case typelib_TypeClass_DOUBLE:
|
||||
if (nREG < MAX_FP_REGS) {
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp2uno_call:fpr=%p\n", fpreg[nREG]);
|
||||
#endif
|
||||
pCppArgs[nPos] = &(fpreg[nREG]);
|
||||
pUnoArgs[nPos] = &(fpreg[nREG]);
|
||||
} else {
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp2uno_call:fpr=%p\n", ovrflw[nREG - MAX_FP_REGS]);
|
||||
#endif
|
||||
pCppArgs[nPos] = &(ovrflw[nREG - MAX_FP_REGS]);
|
||||
pUnoArgs[nPos] = &(ovrflw[nREG - MAX_FP_REGS]);
|
||||
}
|
||||
nREG++;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
if (nREG < MAX_GP_REGS) {
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp2uno_call:gpr=%p\n", gpreg[nREG]);
|
||||
#endif
|
||||
pCppArgs[nPos] = &(gpreg[nREG]);
|
||||
pUnoArgs[nPos] = &(gpreg[nREG]);
|
||||
} else {
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp2uno_call:gpr=%p\n", ovrflw[nREG - MAX_GP_REGS]);
|
||||
#endif
|
||||
pCppArgs[nPos] = &(ovrflw[nREG - MAX_GP_REGS]);
|
||||
pUnoArgs[nPos] = &(ovrflw[nREG - MAX_GP_REGS]);
|
||||
}
|
||||
nREG++;
|
||||
break;
|
||||
|
||||
}
|
||||
// no longer needed
|
||||
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
|
||||
}
|
||||
else // ptr to complex value | ref
|
||||
{
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr,"cpp2uno_call:ptr|ref\n");
|
||||
#endif
|
||||
void *pCppStack;
|
||||
if (nREG < MAX_GP_REGS) {
|
||||
pCppArgs[nPos] = pCppStack = gpreg[nREG];
|
||||
} else {
|
||||
pCppArgs[nPos] = pCppStack = ovrflw[nREG - MAX_GP_REGS];
|
||||
}
|
||||
nREG++;
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp2uno_call:pCppStack=%p\n", pCppStack);
|
||||
#endif
|
||||
|
||||
if (! rParam.bIn) // is pure out
|
||||
{
|
||||
// uno out is unconstructed mem!
|
||||
pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
|
||||
pTempIndices[nTempIndices] = nPos;
|
||||
// will be released at reconversion
|
||||
ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
|
||||
}
|
||||
// is in/inout
|
||||
else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
|
||||
{
|
||||
uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
|
||||
pCppStack, pParamTypeDescr,
|
||||
pThis->getBridge()->getCpp2Uno() );
|
||||
pTempIndices[nTempIndices] = nPos; // has to be reconverted
|
||||
// will be released at reconversion
|
||||
ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp2uno_call:related to interface,%p,%d,pUnoargs[%d]=%p\n",
|
||||
pCppStack, pParamTypeDescr->nSize, nPos, pUnoArgs[nPos]);
|
||||
#endif
|
||||
}
|
||||
else // direct way
|
||||
{
|
||||
pUnoArgs[nPos] = pCppStack;
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp2uno_call:direct,pUnoArgs[%d]=%p\n", nPos, pUnoArgs[nPos]);
|
||||
#endif
|
||||
// no longer needed
|
||||
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp2uno_call2,%p,unoargs=%p\n", pThis->getUnoI()->pDispatcher, pUnoArgs);
|
||||
#endif
|
||||
|
||||
// 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 );
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp2uno_call2,after dispatch\n");
|
||||
#endif
|
||||
|
||||
// in case an exception occurred...
|
||||
if (pUnoExc)
|
||||
{
|
||||
// destruct temporary in/inout params
|
||||
for ( ; nTempIndices--; )
|
||||
{
|
||||
sal_Int32 nIndex = pTempIndices[nTempIndices];
|
||||
|
||||
if (pParams[nIndex].bIn) // is in/inout => was constructed
|
||||
uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndices], 0 );
|
||||
TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
|
||||
}
|
||||
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 ( ; nTempIndices--; )
|
||||
{
|
||||
sal_Int32 nIndex = pTempIndices[nTempIndices];
|
||||
typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* is called on incoming vtable calls
|
||||
* (called by asm snippets)
|
||||
*/
|
||||
typelib_TypeClass cpp_vtable_call(
|
||||
sal_Int32 nFunctionIndex,
|
||||
sal_Int32 nVtableOffset,
|
||||
void ** gpreg, void ** fpreg, void ** ovrflw,
|
||||
sal_uInt64 * pRegisterReturn /* space for register return */ )
|
||||
{
|
||||
static_assert( sizeof(sal_Int64)==sizeof(void *), "### unexpected!" );
|
||||
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "in cpp_vtable_call nFunctionIndex is %d\n", nFunctionIndex);
|
||||
fprintf(stderr, "in cpp_vtable_call nVtableOffset is %d\n", nVtableOffset);
|
||||
fprintf(stderr, "in cpp_vtable_call gp=%p, fp=%p, ov=%p\n", gpreg, fpreg, ovrflw);
|
||||
#endif
|
||||
|
||||
// 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];
|
||||
}
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp_vtable_call, pThis=%p, nFunctionIndex=%d, nVtableOffset=%d\n",
|
||||
pThis, nFunctionIndex, nVtableOffset);
|
||||
#endif
|
||||
|
||||
pThis = static_cast< char * >(pThis) - nVtableOffset;
|
||||
bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
|
||||
bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis );
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp_vtable_call, pCppI=%p\n", pCppI);
|
||||
#endif
|
||||
|
||||
typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
|
||||
|
||||
if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
|
||||
{
|
||||
SAL_WARN(
|
||||
"bridges",
|
||||
"illegal " << OUString::unacquired(&pTypeDescr->aBase.pTypeName)
|
||||
<< " vtable index " << nFunctionIndex << "/"
|
||||
<< pTypeDescr->nMapFunctionIndexToMemberIndex);
|
||||
throw RuntimeException(
|
||||
("illegal " + OUString::unacquired(&pTypeDescr->aBase.pTypeName)
|
||||
+ " vtable index " + OUString::number(nFunctionIndex) + "/"
|
||||
+ OUString::number(pTypeDescr->nMapFunctionIndexToMemberIndex)),
|
||||
(XInterface *)pThis);
|
||||
}
|
||||
|
||||
// determine called method
|
||||
sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
|
||||
assert(nMemberPos < pTypeDescr->nAllMembers);
|
||||
|
||||
TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
|
||||
|
||||
#ifdef BRDEBUG
|
||||
OString cstr( OUStringToOString( aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
|
||||
fprintf(stderr, "calling %s, nFunctionIndex=%d\n", cstr.getStr(), nFunctionIndex );
|
||||
#endif
|
||||
typelib_TypeClass eRet;
|
||||
switch (aMemberDescr.get()->eTypeClass)
|
||||
{
|
||||
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
|
||||
{
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp_vtable_call interface attribute\n");
|
||||
#endif
|
||||
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:
|
||||
{
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp_vtable_call interface method\n");
|
||||
#endif
|
||||
// is METHOD
|
||||
switch (nFunctionIndex)
|
||||
{
|
||||
case 1: // acquire()
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp_vtable_call method acquire\n");
|
||||
#endif
|
||||
pCppI->acquireProxy(); // non virtual call!
|
||||
eRet = typelib_TypeClass_VOID;
|
||||
break;
|
||||
case 2: // release()
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp_vtable_call method release\n");
|
||||
#endif
|
||||
pCppI->releaseProxy(); // non virtual call!
|
||||
eRet = typelib_TypeClass_VOID;
|
||||
break;
|
||||
case 0: // queryInterface() opt
|
||||
{
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp_vtable_call method query interface opt\n");
|
||||
#endif
|
||||
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:
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp_vtable_call method query interface\n");
|
||||
#endif
|
||||
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:
|
||||
{
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "cpp_vtable_call no member\n");
|
||||
#endif
|
||||
throw RuntimeException( "no member description found!", (XInterface *)pThis );
|
||||
}
|
||||
}
|
||||
|
||||
return eRet;
|
||||
}
|
||||
|
||||
extern "C" void privateSnippetExecutor( ... );
|
||||
|
||||
int const codeSnippetSize = 0x44;
|
||||
|
||||
unsigned char * codeSnippet( unsigned char * code,
|
||||
sal_Int32 functionIndex, sal_Int32 vtableOffset,
|
||||
bool bHasHiddenParam) SAL_THROW(())
|
||||
{
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr,"in codeSnippet functionIndex is %d\n", functionIndex);
|
||||
fprintf(stderr,"in codeSnippet vtableOffset is %d\n", vtableOffset);
|
||||
fflush(stderr);
|
||||
#endif
|
||||
|
||||
if ( bHasHiddenParam )
|
||||
functionIndex |= 0x80000000;
|
||||
|
||||
unsigned int * p = (unsigned int *) code;
|
||||
|
||||
assert((((unsigned long)code) & 0x3) == 0 ); //aligned to 4 otherwise a mistake
|
||||
|
||||
/* generate this code */
|
||||
/*
|
||||
# index
|
||||
0: 3c020000 lui v0,0x0
|
||||
4: 34420000 ori v0,v0,0x0
|
||||
# privateSnippetExecutor
|
||||
8: 3c0c0000 lui t0,0x0
|
||||
c: 358c0000 ori t0,t0,0x0
|
||||
10: 000c6438 dsll t0,t0,0x10
|
||||
14: 358c0000 ori t0,t0,0x0
|
||||
18: 000c6438 dsll t0,t0,0x10
|
||||
1c: 358c0000 ori t0,t0,0x0
|
||||
# cpp_vtable_call
|
||||
20: 3c190000 lui t9,0x0
|
||||
24: 37390000 ori t9,t9,0x0
|
||||
28: 0019cc38 dsll t9,t9,0x10
|
||||
2c: 37390000 ori t9,t9,0x0
|
||||
30: 0019cc38 dsll t9,t9,0x10
|
||||
34: 37390000 ori t9,t9,0x0
|
||||
# offset
|
||||
38: 3c030000 lui v1,0x0
|
||||
3c: 01800008 jr t0
|
||||
40: 34630000 ori v1,v1,0x0
|
||||
*/
|
||||
|
||||
* p++ = 0x3c020000 | ((functionIndex>>16) & 0x0000ffff);
|
||||
* p++ = 0x34420000 | (functionIndex & 0x0000ffff);
|
||||
* p++ = 0x3c0c0000 | ((((unsigned long)privateSnippetExecutor) >> 48) & 0x0000ffff);
|
||||
* p++ = 0x358c0000 | ((((unsigned long)privateSnippetExecutor) >> 32) & 0x0000ffff);
|
||||
* p++ = 0x000c6438;
|
||||
* p++ = 0x358c0000 | ((((unsigned long)privateSnippetExecutor) >> 16) & 0x0000ffff);
|
||||
* p++ = 0x000c6438;
|
||||
* p++ = 0x358c0000 | (((unsigned long)privateSnippetExecutor) & 0x0000ffff);
|
||||
* p++ = 0x3c190000 | ((((unsigned long)cpp_vtable_call) >> 48) & 0x0000ffff);
|
||||
* p++ = 0x37390000 | ((((unsigned long)cpp_vtable_call) >> 32) & 0x0000ffff);
|
||||
* p++ = 0x0019cc38;
|
||||
* p++ = 0x37390000 | ((((unsigned long)cpp_vtable_call) >> 16) & 0x0000ffff);
|
||||
* p++ = 0x0019cc38;
|
||||
* p++ = 0x37390000 | (((unsigned long)cpp_vtable_call) & 0x0000ffff);
|
||||
* p++ = 0x3c030000 | ((vtableOffset>>16) & 0x0000ffff);
|
||||
* p++ = 0x01800008;
|
||||
* p++ = 0x34630000 | (vtableOffset & 0x0000ffff);
|
||||
return (code + codeSnippetSize);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const *bptr, unsigned char const *eptr)
|
||||
{
|
||||
#ifndef ANDROID
|
||||
(void) bptr;
|
||||
(void) eptr;
|
||||
sysmips(FLUSH_CACHE, 0, 0, 0);
|
||||
#else
|
||||
cacheflush((long) bptr, (long) eptr, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
|
||||
|
||||
bridges::cpp_uno::shared::VtableFactory::Slot *
|
||||
bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
|
||||
{
|
||||
return static_cast< Slot * >(block) + 2;
|
||||
}
|
||||
|
||||
|
||||
sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
|
||||
sal_Int32 slotCount)
|
||||
{
|
||||
return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
|
||||
}
|
||||
|
||||
bridges::cpp_uno::shared::VtableFactory::Slot *
|
||||
bridges::cpp_uno::shared::VtableFactory::initializeBlock(
|
||||
void * block, sal_Int32 slotCount, sal_Int32,
|
||||
typelib_InterfaceTypeDescription *)
|
||||
{
|
||||
Slot * slots = mapBlockToVtable(block);
|
||||
slots[-2].fn = 0; //null
|
||||
slots[-1].fn = 0; //destructor
|
||||
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 functionOffset,
|
||||
sal_Int32 functionCount, sal_Int32 vtableOffset)
|
||||
{
|
||||
(*slots) -= functionCount;
|
||||
Slot * s = *slots;
|
||||
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "in addLocalFunctions functionOffset is %d\n", functionOffset);
|
||||
fprintf(stderr, "in addLocalFunctions vtableOffset is %d\n", vtableOffset);
|
||||
fprintf(stderr, "nMembers=%d\n", type->nMembers);
|
||||
fflush(stderr);
|
||||
#endif
|
||||
|
||||
for (sal_Int32 i = 0; i < type->nMembers; ++i) {
|
||||
typelib_TypeDescription * member = 0;
|
||||
TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
|
||||
assert(member != 0);
|
||||
switch (member->eTypeClass) {
|
||||
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
|
||||
// Getter:
|
||||
(s++)->fn = code + writetoexecdiff;
|
||||
code = codeSnippet(
|
||||
code, functionOffset++, vtableOffset,
|
||||
CPPU_CURRENT_NAMESPACE::return_in_hidden_param(
|
||||
reinterpret_cast<
|
||||
typelib_InterfaceAttributeTypeDescription * >(
|
||||
member)->pAttributeTypeRef));
|
||||
|
||||
// Setter:
|
||||
if (!reinterpret_cast<
|
||||
typelib_InterfaceAttributeTypeDescription * >(
|
||||
member)->bReadOnly)
|
||||
{
|
||||
(s++)->fn = code + writetoexecdiff;
|
||||
code = codeSnippet(code, functionOffset++, vtableOffset, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case typelib_TypeClass_INTERFACE_METHOD:
|
||||
(s++)->fn = code + writetoexecdiff;
|
||||
code = codeSnippet(
|
||||
code, functionOffset++, vtableOffset,
|
||||
CPPU_CURRENT_NAMESPACE::return_in_hidden_param(
|
||||
reinterpret_cast<
|
||||
typelib_InterfaceMethodTypeDescription * >(
|
||||
member)->pReturnTypeRef));
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
TYPELIB_DANGER_RELEASE(member);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
300
bridges/source/cpp_uno/gcc3_linux_mips64/except.cxx
Normal file
300
bridges/source/cpp_uno/gcc3_linux_mips64/except.cxx
Normal file
@ -0,0 +1,300 @@
|
||||
/* -*- 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 .
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
#include <cxxabi.h>
|
||||
#include <rtl/strbuf.hxx>
|
||||
#include <rtl/ustrbuf.hxx>
|
||||
#include <sal/log.hxx>
|
||||
#include <osl/mutex.hxx>
|
||||
|
||||
#include <com/sun/star/uno/genfunc.hxx>
|
||||
#include <typelib/typedescription.hxx>
|
||||
#include <uno/any2.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include "share.hxx"
|
||||
|
||||
|
||||
using namespace ::std;
|
||||
using namespace ::osl;
|
||||
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 )
|
||||
{
|
||||
#if defined BRIDGES_DEBUG
|
||||
char const * start = p;
|
||||
#endif
|
||||
|
||||
// example: N3com3sun4star4lang24IllegalArgumentExceptionE
|
||||
|
||||
OUStringBuffer buf( 64 );
|
||||
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( '.' );
|
||||
}
|
||||
|
||||
#if defined BRIDGES_DEBUG
|
||||
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 std::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();
|
||||
~RTTI();
|
||||
|
||||
type_info * getRTTI( typelib_CompoundTypeDescription * );
|
||||
};
|
||||
|
||||
RTTI::RTTI()
|
||||
: m_hApp( dlopen( 0, RTLD_LAZY ) )
|
||||
{
|
||||
}
|
||||
|
||||
RTTI::~RTTI()
|
||||
{
|
||||
dlclose( m_hApp );
|
||||
}
|
||||
|
||||
|
||||
type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr )
|
||||
{
|
||||
type_info * rtti;
|
||||
|
||||
OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName;
|
||||
|
||||
MutexGuard guard( m_mutex );
|
||||
t_rtti_map::const_iterator iRttiFind( m_rttis.find( unoName ) );
|
||||
if (iRttiFind == m_rttis.end())
|
||||
{
|
||||
// RTTI symbol
|
||||
OStringBuffer buf( 64 );
|
||||
buf.append( "_ZTIN" );
|
||||
sal_Int32 index = 0;
|
||||
do
|
||||
{
|
||||
OUString token( unoName.getToken( 0, '.', index ) );
|
||||
buf.append( token.getLength() );
|
||||
OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) );
|
||||
buf.append( c_token );
|
||||
}
|
||||
while (index >= 0);
|
||||
buf.append( 'E' );
|
||||
|
||||
OString symName( buf.makeStringAndClear() );
|
||||
rtti = (type_info *)dlsym( m_hApp, symName.getStr() );
|
||||
|
||||
if (rtti)
|
||||
{
|
||||
pair< t_rtti_map::iterator, bool > insertion(
|
||||
m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
|
||||
assert(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 defined BRIDGES_DEBUG
|
||||
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 ) ) );
|
||||
assert(insertion.second && "### inserting new generated rtti failed?!");
|
||||
}
|
||||
else // taking already generated rtti
|
||||
{
|
||||
rtti = iFind->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rtti = iRttiFind->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 );
|
||||
assert(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 defined BRIDGES_DEBUG
|
||||
OString cstr(
|
||||
OUStringToOString(
|
||||
OUString::unacquired( &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 );
|
||||
assert(pTypeDescr);
|
||||
if (! pTypeDescr)
|
||||
{
|
||||
throw RuntimeException(
|
||||
OUString("cannot get typedescription for type ") +
|
||||
OUString::unacquired( &pUnoExc->pType->pTypeName ) );
|
||||
}
|
||||
|
||||
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 );
|
||||
assert(rtti && "### no rtti for throwing exception!");
|
||||
if (! rtti)
|
||||
{
|
||||
throw RuntimeException(
|
||||
OUString("no rtti for type ") +
|
||||
OUString::unacquired( &pUnoExc->pType->pTypeName ) );
|
||||
}
|
||||
}
|
||||
|
||||
__cxa_throw( pCppExc, rtti, deleteException );
|
||||
}
|
||||
|
||||
void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno )
|
||||
{
|
||||
if (! header)
|
||||
{
|
||||
RuntimeException aRE( "no exception header!" );
|
||||
Type const & rType = cppu::UnoType<decltype(aRE)>::get();
|
||||
uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
|
||||
SAL_WARN("bridges", aRE.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
typelib_TypeDescription * pExcTypeDescr = 0;
|
||||
OUString unoName( toUNOname( header->exceptionType->name() ) );
|
||||
#if defined BRIDGES_DEBUG
|
||||
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("exception type not found: ") + unoName );
|
||||
Type const & rType = cppu::UnoType<decltype(aRE)>::get();
|
||||
uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
|
||||
SAL_WARN("bridges", aRE.Message);
|
||||
}
|
||||
else
|
||||
{
|
||||
// construct uno exception any
|
||||
uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno );
|
||||
typelib_typedescription_release( pExcTypeDescr );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
91
bridges/source/cpp_uno/gcc3_linux_mips64/share.hxx
Normal file
91
bridges/source/cpp_uno/gcc3_linux_mips64/share.hxx
Normal file
@ -0,0 +1,91 @@
|
||||
/* -*- 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 .
|
||||
*/
|
||||
#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_GCC3_LINUX_MIPS64_SHARE_HXX
|
||||
#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_GCC3_LINUX_MIPS64_SHARE_HXX
|
||||
|
||||
#include "uno/mapping.h"
|
||||
|
||||
#include <typeinfo>
|
||||
#include <exception>
|
||||
#include <cstddef>
|
||||
|
||||
#define MAX_GP_REGS (8)
|
||||
#define MAX_FP_REGS (8)
|
||||
|
||||
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 );
|
||||
|
||||
bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef );
|
||||
}
|
||||
|
||||
#endif
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
576
bridges/source/cpp_uno/gcc3_linux_mips64/uno2cpp.cxx
Normal file
576
bridges/source/cpp_uno/gcc3_linux_mips64/uno2cpp.cxx
Normal file
@ -0,0 +1,576 @@
|
||||
/* -*- 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 .
|
||||
*/
|
||||
|
||||
#include <malloc.h>
|
||||
#include <cstring>
|
||||
|
||||
#include <com/sun/star/uno/genfunc.hxx>
|
||||
#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"
|
||||
|
||||
//#define BRDEBUG
|
||||
#ifdef BRDEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#define INSERT_FLOAT_DOUBLE( pSV, nr, pFPR, pDS ) \
|
||||
if ( nr < MAX_FP_REGS ) \
|
||||
pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \
|
||||
else \
|
||||
*pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim!
|
||||
|
||||
#define INSERT_INT64( pSV, nr, pGPR, pDS ) \
|
||||
if ( nr < MAX_GP_REGS ) \
|
||||
pGPR[nr++] = *reinterpret_cast<sal_Int64 *>( pSV ); \
|
||||
else \
|
||||
*pDS++ = *reinterpret_cast<sal_Int64 *>( pSV );
|
||||
|
||||
#define INSERT_INT32( pSV, nr, pGPR, pDS ) \
|
||||
if ( nr < MAX_GP_REGS ) \
|
||||
pGPR[nr++] = *reinterpret_cast<sal_Int32 *>( pSV ); \
|
||||
else \
|
||||
*pDS++ = *reinterpret_cast<sal_Int32 *>( pSV );
|
||||
|
||||
#define INSERT_INT16( pSV, nr, pGPR, pDS ) \
|
||||
if ( nr < MAX_GP_REGS ) \
|
||||
pGPR[nr++] = *reinterpret_cast<sal_Int16 *>( pSV ); \
|
||||
else \
|
||||
*pDS++ = *reinterpret_cast<sal_Int16 *>( pSV );
|
||||
|
||||
#define INSERT_UINT16( pSV, nr, pGPR, pDS ) \
|
||||
if ( nr < MAX_GP_REGS ) \
|
||||
pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
|
||||
else \
|
||||
*pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
|
||||
|
||||
#define INSERT_INT8( pSV, nr, pGPR, pDS ) \
|
||||
if ( nr < MAX_GP_REGS ) \
|
||||
pGPR[nr++] = *reinterpret_cast<sal_Int8 *>( pSV ); \
|
||||
else \
|
||||
*pDS++ = *reinterpret_cast<sal_Int8 *>( pSV );
|
||||
|
||||
using namespace ::com::sun::star::uno;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
bool isReturnInFPR(const typelib_TypeDescription * pTypeDescr, sal_uInt32 & nSize)
|
||||
{
|
||||
const typelib_CompoundTypeDescription *p =
|
||||
reinterpret_cast<const typelib_CompoundTypeDescription*>( pTypeDescr );
|
||||
|
||||
for (sal_Int32 i = 0; i < p->nMembers; ++i)
|
||||
{
|
||||
typelib_TypeDescriptionReference *pTypeInStruct = p->ppTypeRefs[ i ];
|
||||
|
||||
switch (pTypeInStruct->eTypeClass)
|
||||
{
|
||||
case typelib_TypeClass_STRUCT:
|
||||
case typelib_TypeClass_EXCEPTION:
|
||||
{
|
||||
typelib_TypeDescription * t = 0;
|
||||
TYPELIB_DANGER_GET(&t, pTypeInStruct);
|
||||
bool isFPR = isReturnInFPR(t, nSize);
|
||||
TYPELIB_DANGER_RELEASE(t);
|
||||
if (!isFPR)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case typelib_TypeClass_FLOAT:
|
||||
case typelib_TypeClass_DOUBLE:
|
||||
if (nSize >= 16)
|
||||
return false;
|
||||
nSize += 8;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void fillReturn(const typelib_TypeDescription * pTypeDescr,
|
||||
sal_Int64 * gret, double * fret, void * pRegisterReturn)
|
||||
{
|
||||
sal_uInt32 nSize = 0;
|
||||
if (isReturnInFPR(pTypeDescr, nSize))
|
||||
{
|
||||
reinterpret_cast<double *>( pRegisterReturn )[0] = fret[0];
|
||||
reinterpret_cast<double *>( pRegisterReturn )[1] = fret[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
reinterpret_cast<sal_Int64 *>( pRegisterReturn )[0] = gret[0];
|
||||
reinterpret_cast<sal_Int64 *>( pRegisterReturn )[1] = gret[1];
|
||||
}
|
||||
}
|
||||
|
||||
static void callVirtualMethod(
|
||||
void * pAdjustedThisPtr,
|
||||
sal_Int32 nVtableIndex,
|
||||
void * pRegisterReturn,
|
||||
typelib_TypeDescriptionReference * pReturnTypeRef,
|
||||
bool bSimpleReturn,
|
||||
sal_uInt64 *pStack,
|
||||
sal_uInt32 nStack,
|
||||
sal_uInt64 *pGPR,
|
||||
double *pFPR,
|
||||
sal_uInt32 nREG)
|
||||
{
|
||||
// Should not happen, but...
|
||||
static_assert( MAX_GP_REGS == MAX_FP_REGS );
|
||||
if ( nREG > MAX_GP_REGS )
|
||||
nREG = MAX_GP_REGS;
|
||||
|
||||
// Get pointer to method
|
||||
sal_uInt64 pMethod = *((sal_uInt64 *)pAdjustedThisPtr);
|
||||
pMethod += 8 * nVtableIndex;
|
||||
void *mfunc = (void *) *((sal_uInt64 *)pMethod);
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "calling function %p\n", mfunc);
|
||||
#endif
|
||||
|
||||
// Load parameters to stack, if necessary
|
||||
sal_uInt64* pCallStack = NULL;
|
||||
if ( nStack )
|
||||
{
|
||||
// 16-bytes aligned
|
||||
sal_uInt32 nStackBytes = ( ( nStack + 1 ) >> 1 ) * 16;
|
||||
pCallStack = (sal_uInt64 *) __builtin_alloca( nStackBytes );
|
||||
std::memcpy( pCallStack, pStack, nStackBytes );
|
||||
}
|
||||
|
||||
sal_Int64 gret[2];
|
||||
double fret[2];
|
||||
asm volatile (
|
||||
".set push \n\t"
|
||||
".set mips64 \n\t"
|
||||
// Fill the general purpose registers
|
||||
"ld $4, 0(%[gpr]) \n\t"
|
||||
"ld $5, 8(%[gpr]) \n\t"
|
||||
"ld $6, 16(%[gpr]) \n\t"
|
||||
"ld $7, 24(%[gpr]) \n\t"
|
||||
"ld $8, 32(%[gpr]) \n\t"
|
||||
"ld $9, 40(%[gpr]) \n\t"
|
||||
"ld $10, 48(%[gpr]) \n\t"
|
||||
"ld $11, 56(%[gpr]) \n\t"
|
||||
// Fill the floating pointer registers
|
||||
"ldc1 $f12, 0(%[fpr]) \n\t"
|
||||
"ldc1 $f13, 8(%[fpr]) \n\t"
|
||||
"ldc1 $f14, 16(%[fpr]) \n\t"
|
||||
"ldc1 $f15, 24(%[fpr]) \n\t"
|
||||
"ldc1 $f16, 32(%[fpr]) \n\t"
|
||||
"ldc1 $f17, 40(%[fpr]) \n\t"
|
||||
"ldc1 $f18, 48(%[fpr]) \n\t"
|
||||
"ldc1 $f19, 56(%[fpr]) \n\t"
|
||||
// Perform the call
|
||||
"jalr %[mfunc] \n\t"
|
||||
// Fill the return values
|
||||
"move %[gret1], $2 \n\t"
|
||||
"move %[gret2], $3 \n\t"
|
||||
"mov.d %[fret1], $f0 \n\t"
|
||||
"mov.d %[fret2], $f2 \n\t"
|
||||
".set pop \n\t"
|
||||
:[gret1]"=r"(gret[0]), [gret2]"=r"(gret[1]),
|
||||
[fret1]"=f"(fret[0]), [fret2]"=f"(fret[1])
|
||||
:[gpr]"r"(pGPR), [fpr]"r"(pFPR), [mfunc]"c"(mfunc),
|
||||
[stack]"m"(pCallStack) // dummy input to prevent the compiler from optimizing the alloca out
|
||||
:"$2", "$3", "$4", "$5", "$6", "$7", "$8",
|
||||
"$9", "$10", "$11", "$31",
|
||||
"$f0", "$f2", "$f12", "$f13", "$f14", "$f15",
|
||||
"$f16", "$f17", "$f18", "$f19", "memory"
|
||||
);
|
||||
|
||||
switch (pReturnTypeRef->eTypeClass)
|
||||
{
|
||||
case typelib_TypeClass_HYPER:
|
||||
case typelib_TypeClass_UNSIGNED_HYPER:
|
||||
case typelib_TypeClass_LONG:
|
||||
case typelib_TypeClass_UNSIGNED_LONG:
|
||||
case typelib_TypeClass_ENUM:
|
||||
case typelib_TypeClass_CHAR:
|
||||
case typelib_TypeClass_SHORT:
|
||||
case typelib_TypeClass_UNSIGNED_SHORT:
|
||||
case typelib_TypeClass_BOOLEAN:
|
||||
case typelib_TypeClass_BYTE:
|
||||
*reinterpret_cast<sal_Int64 *>( pRegisterReturn ) = gret[0];
|
||||
break;
|
||||
case typelib_TypeClass_FLOAT:
|
||||
case typelib_TypeClass_DOUBLE:
|
||||
*reinterpret_cast<double *>( pRegisterReturn ) = fret[0];
|
||||
break;
|
||||
case typelib_TypeClass_STRUCT:
|
||||
case typelib_TypeClass_EXCEPTION:
|
||||
{
|
||||
sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize;
|
||||
if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0)
|
||||
{
|
||||
typelib_TypeDescription * pTypeDescr = 0;
|
||||
TYPELIB_DANGER_GET( &pTypeDescr, pReturnTypeRef );
|
||||
fillReturn(pTypeDescr, gret, fret, pRegisterReturn);
|
||||
TYPELIB_DANGER_RELEASE( pTypeDescr );
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr,"unhandled return type %u\n", pReturnTypeRef->eTypeClass);
|
||||
#endif
|
||||
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 )
|
||||
{
|
||||
// max space for: [complex ret ptr], values|ptr ...
|
||||
sal_uInt64 *pStack = (sal_uInt64 *)__builtin_alloca( ((nParams+3) * sizeof(sal_Int64)) );
|
||||
sal_uInt64 *pStackStart = pStack;
|
||||
|
||||
sal_uInt64 pGPR[MAX_GP_REGS];
|
||||
double pFPR[MAX_FP_REGS];
|
||||
sal_uInt32 nREG = 0;
|
||||
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "in cpp_call\n");
|
||||
#endif
|
||||
|
||||
// return
|
||||
typelib_TypeDescription * pReturnTypeDescr = 0;
|
||||
TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
|
||||
assert( pReturnTypeDescr, "### expected return type description!" );
|
||||
|
||||
void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
|
||||
|
||||
bool bSimpleReturn = true;
|
||||
if (pReturnTypeDescr)
|
||||
{
|
||||
if ( CPPU_CURRENT_NAMESPACE::return_in_hidden_param( pReturnTypeRef ) )
|
||||
{
|
||||
bSimpleReturn = false;
|
||||
// complex return via ptr
|
||||
pCppReturn = bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )?
|
||||
__builtin_alloca( pReturnTypeDescr->nSize ) : pUnoReturn;
|
||||
INSERT_INT64( &pCppReturn, nREG, pGPR, pStack );
|
||||
}
|
||||
else
|
||||
{
|
||||
pCppReturn = pUnoReturn; // direct way for simple types
|
||||
}
|
||||
}
|
||||
|
||||
// push this
|
||||
void* pAdjustedThisPtr = reinterpret_cast< void **>( pThis->getCppI() ) + aVtableSlot.offset;
|
||||
INSERT_INT64( &pAdjustedThisPtr, nREG, pGPR, pStack );
|
||||
|
||||
// args
|
||||
void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
|
||||
// indices of values this have to be converted (interface conversion cpp<=>uno)
|
||||
sal_Int32 * pTempIndices = (sal_Int32 *)(pCppArgs + nParams);
|
||||
// type descriptions for reconversions
|
||||
typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
|
||||
|
||||
sal_Int32 nTempIndices = 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_LONG:
|
||||
case typelib_TypeClass_UNSIGNED_LONG:
|
||||
case typelib_TypeClass_ENUM:
|
||||
INSERT_INT32( pCppArgs[nPos], nREG, pGPR, pStack );
|
||||
break;
|
||||
case typelib_TypeClass_CHAR:
|
||||
case typelib_TypeClass_SHORT:
|
||||
INSERT_INT16( pCppArgs[nPos], nREG, pGPR, pStack );
|
||||
break;
|
||||
case typelib_TypeClass_UNSIGNED_SHORT:
|
||||
INSERT_UINT16( pCppArgs[nPos], nREG, pGPR, pStack );
|
||||
break;
|
||||
case typelib_TypeClass_BOOLEAN:
|
||||
case typelib_TypeClass_BYTE:
|
||||
INSERT_INT8( pCppArgs[nPos], nREG, pGPR, pStack );
|
||||
break;
|
||||
case typelib_TypeClass_FLOAT:
|
||||
case typelib_TypeClass_DOUBLE:
|
||||
INSERT_FLOAT_DOUBLE( pCppArgs[nPos], nREG, pFPR, pStack );
|
||||
break;
|
||||
case typelib_TypeClass_HYPER:
|
||||
case typelib_TypeClass_UNSIGNED_HYPER:
|
||||
INSERT_INT64( pCppArgs[nPos], nREG, pGPR, 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 );
|
||||
pTempIndices[nTempIndices] = nPos; // default constructed for cpp call
|
||||
// will be released at reconversion
|
||||
ppTempParamTypeDescr[nTempIndices++] = 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() );
|
||||
|
||||
pTempIndices[nTempIndices] = nPos; // has to be reconverted
|
||||
// will be released at reconversion
|
||||
ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
|
||||
}
|
||||
else // direct way
|
||||
{
|
||||
pCppArgs[nPos] = pUnoArgs[nPos];
|
||||
// no longer needed
|
||||
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
|
||||
}
|
||||
INSERT_INT64( &(pCppArgs[nPos]), nREG, pGPR, pStack );
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
callVirtualMethod(
|
||||
pAdjustedThisPtr, aVtableSlot.index,
|
||||
pCppReturn, pReturnTypeRef, bSimpleReturn,
|
||||
pStackStart, ( pStack - pStackStart ),
|
||||
pGPR, pFPR, nREG);
|
||||
// NO exception occurred...
|
||||
*ppUnoExc = 0;
|
||||
|
||||
// reconvert temporary params
|
||||
for ( ; nTempIndices--; )
|
||||
{
|
||||
sal_Int32 nIndex = pTempIndices[nTempIndices];
|
||||
typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
|
||||
|
||||
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 ( ; nTempIndices--; )
|
||||
{
|
||||
sal_Int32 nIndex = pTempIndices[nTempIndices];
|
||||
// destroy temp cpp param => cpp: every param was constructed
|
||||
uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndices], cpp_release );
|
||||
TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
|
||||
}
|
||||
// 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);
|
||||
//typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
|
||||
|
||||
#ifdef BRDEBUG
|
||||
fprintf(stderr, "in dispatch\n");
|
||||
#endif
|
||||
|
||||
switch (pMemberDescr->eTypeClass)
|
||||
{
|
||||
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
|
||||
{
|
||||
|
||||
VtableSlot aVtableSlot(
|
||||
getVtableSlot(
|
||||
reinterpret_cast<
|
||||
typelib_InterfaceAttributeTypeDescription const * >(
|
||||
pMemberDescr)));
|
||||
|
||||
if (pReturn)
|
||||
{
|
||||
// dependent dispatch
|
||||
cpp_call(
|
||||
pThis, aVtableSlot,
|
||||
((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
|
||||
0, 0, // no params
|
||||
pReturn, pArgs, ppException );
|
||||
}
|
||||
else
|
||||
{
|
||||
// is SET
|
||||
typelib_MethodParameter aParam;
|
||||
aParam.pTypeRef =
|
||||
((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
|
||||
aParam.bIn = sal_True;
|
||||
aParam.bOut = sal_False;
|
||||
|
||||
typelib_TypeDescriptionReference * pReturnTypeRef = 0;
|
||||
OUString aVoidName("void");
|
||||
typelib_typedescriptionreference_new(
|
||||
&pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
|
||||
|
||||
// dependent dispatch
|
||||
aVtableSlot.index += 1; //get then set method
|
||||
cpp_call(
|
||||
pThis, aVtableSlot,
|
||||
pReturnTypeRef,
|
||||
1, &aParam,
|
||||
pReturn, pArgs, ppException );
|
||||
|
||||
typelib_typedescriptionreference_release( pReturnTypeRef );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case typelib_TypeClass_INTERFACE_METHOD:
|
||||
{
|
||||
|
||||
VtableSlot aVtableSlot(
|
||||
getVtableSlot(
|
||||
reinterpret_cast<
|
||||
typelib_InterfaceMethodTypeDescription const * >(
|
||||
pMemberDescr)));
|
||||
switch (aVtableSlot.index)
|
||||
{
|
||||
// standard calls
|
||||
case 1: // acquire uno interface
|
||||
(*pUnoI->acquire)( pUnoI );
|
||||
*ppException = 0;
|
||||
break;
|
||||
case 2: // release uno interface
|
||||
(*pUnoI->release)( pUnoI );
|
||||
*ppException = 0;
|
||||
break;
|
||||
case 0: // queryInterface() opt
|
||||
{
|
||||
typelib_TypeDescription * pTD = 0;
|
||||
TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
|
||||
if (pTD)
|
||||
{
|
||||
uno_Interface * pInterface = 0;
|
||||
(*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(pThis->pBridge->getUnoEnv(),
|
||||
(void **)&pInterface, pThis->oid.pData,
|
||||
(typelib_InterfaceTypeDescription *)pTD );
|
||||
|
||||
if (pInterface)
|
||||
{
|
||||
::uno_any_construct(
|
||||
reinterpret_cast< uno_Any * >( pReturn ),
|
||||
&pInterface, pTD, 0 );
|
||||
(*pInterface->release)( pInterface );
|
||||
TYPELIB_DANGER_RELEASE( pTD );
|
||||
*ppException = 0;
|
||||
break;
|
||||
}
|
||||
TYPELIB_DANGER_RELEASE( pTD );
|
||||
}
|
||||
} // else perform queryInterface()
|
||||
default:
|
||||
// dependent dispatch
|
||||
cpp_call(
|
||||
pThis, aVtableSlot,
|
||||
((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
|
||||
((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
|
||||
((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
|
||||
pReturn, pArgs, ppException );
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
::com::sun::star::uno::RuntimeException aExc(
|
||||
OUString("illegal member type description!"),
|
||||
::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
|
||||
|
||||
Type const & rExcType = cppu::UnoType<decltype(aExc)>::get();
|
||||
// binary identical null reference
|
||||
::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}}}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
Loading…
x
Reference in New Issue
Block a user