1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cpp2uno.cxx,v $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 #include "precompiled_bridges.hxx"
33 #include "sal/config.h"
39 #include "bridges/cpp_uno/shared/bridge.hxx"
40 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
41 #include "bridges/cpp_uno/shared/types.hxx"
42 #include "bridges/cpp_uno/shared/vtablefactory.hxx"
43 #include "com/sun/star/uno/genfunc.hxx"
44 #include "osl/diagnose.h"
45 #include "sal/alloca.h"
46 #include "sal/types.h"
47 #include "typelib/typeclass.h"
48 #include "typelib/typedescription.h"
49 #include "typelib/typedescription.hxx"
53 #include "exceptions.hxx"
54 #include "flushcode.hxx"
56 #include "isdirectreturntype.hxx"
57 #include "vtableslotcall.hxx"
61 namespace css
= com::sun::star
;
63 void loadFpRegsFromStruct(typelib_TypeDescription
* type
, void * data
) {
64 for (typelib_CompoundTypeDescription
* t
=
65 reinterpret_cast< typelib_CompoundTypeDescription
* >(type
);
66 t
!= NULL
; t
= t
->pBaseTypeDescription
)
68 for (sal_Int32 i
= 0; i
< t
->nMembers
; ++i
) {
69 switch (t
->ppTypeRefs
[i
]->eTypeClass
) {
70 case typelib_TypeClass_FLOAT
:
71 switch (t
->pMemberOffsets
[i
]) {
73 fp_loadf0(reinterpret_cast< float * >(data
));
76 fp_loadf1(reinterpret_cast< float * >(data
) + 1);
79 fp_loadf2(reinterpret_cast< float * >(data
) + 2);
82 fp_loadf3(reinterpret_cast< float * >(data
) + 3);
85 fp_loadf4(reinterpret_cast< float * >(data
) + 4);
88 fp_loadf5(reinterpret_cast< float * >(data
) + 5);
91 fp_loadf6(reinterpret_cast< float * >(data
) + 6);
94 fp_loadf7(reinterpret_cast< float * >(data
) + 7);
101 case typelib_TypeClass_DOUBLE
:
102 switch (t
->pMemberOffsets
[i
]) {
104 fp_loadd0(reinterpret_cast< double * >(data
));
107 fp_loadd2(reinterpret_cast< double * >(data
) + 1);
110 fp_loadd4(reinterpret_cast< double * >(data
) + 2);
113 fp_loadd6(reinterpret_cast< double * >(data
) + 3);
120 case typelib_TypeClass_STRUCT
:
122 typelib_TypeDescription
* td
= NULL
;
123 TYPELIB_DANGER_GET(&td
, t
->ppTypeRefs
[i
]);
124 loadFpRegsFromStruct(td
, data
);
125 TYPELIB_DANGER_RELEASE(td
);
134 bridges::cpp_uno::shared::CppInterfaceProxy
* proxy
,
135 css::uno::TypeDescription
const & description
,
136 bool directReturn
, typelib_TypeDescriptionReference
* returnType
,
137 sal_Int32 count
, typelib_MethodParameter
* parameters
,
138 unsigned long * callStack
)
140 typelib_TypeDescription
* rtd
= NULL
;
141 if (returnType
!= NULL
) {
142 TYPELIB_DANGER_GET(&rtd
, returnType
);
145 rtd
!= NULL
&& bridges::cpp_uno::shared::relatesToInterfaceType(rtd
);
146 OSL_ASSERT(!(directReturn
&& retconv
));
151 retin
= returnType
== NULL
? NULL
: retbuf
;
153 retout
= reinterpret_cast< void * >(callStack
[0]);
154 retin
= retconv
? alloca(rtd
->nSize
) : retout
;
156 void ** args
= static_cast< void ** >(alloca(count
* sizeof (void *)));
157 void ** cppArgs
= static_cast< void ** >(alloca(count
* sizeof (void *)));
158 typelib_TypeDescription
** argtds
=
159 static_cast< typelib_TypeDescription
** >(
160 alloca(count
* sizeof (typelib_TypeDescription
*)));
161 union fp
{ float f
; double d
; };
163 sal_Int32 stackPos
= directReturn
? 1 : 2; // skip return ptr and this ptr
164 for (sal_Int32 i
= 0; i
< count
; ++i
) {
165 typelib_TypeDescription
* ptd
= NULL
;
166 TYPELIB_DANGER_GET(&ptd
, parameters
[i
].pTypeRef
);
167 if (!parameters
[i
].bOut
&& bridges::cpp_uno::shared::isSimpleType(ptd
))
169 switch (ptd
->eTypeClass
) {
170 case typelib_TypeClass_FLOAT
:
171 if (stackPos
<= 15) {
174 fp_storef3(&copies
[0].f
);
177 fp_storef5(&copies
[1].f
);
180 fp_storef7(&copies
[2].f
);
183 fp_storef9(&copies
[3].f
);
186 fp_storef11(&copies
[4].f
);
189 fp_storef13(&copies
[5].f
);
192 fp_storef15(&copies
[6].f
);
195 fp_storef17(&copies
[7].f
);
198 fp_storef19(&copies
[8].f
);
201 fp_storef21(&copies
[9].f
);
204 fp_storef23(&copies
[10].f
);
207 fp_storef25(&copies
[11].f
);
210 fp_storef27(&copies
[12].f
);
213 fp_storef29(&copies
[13].f
);
216 fp_storef31(&copies
[14].f
);
222 args
[i
] = &copies
[stackPos
- 1].f
;
224 args
[i
] = reinterpret_cast< char * >(callStack
+ stackPos
) +
225 (sizeof (unsigned long) - sizeof (float));
228 case typelib_TypeClass_DOUBLE
:
229 if (stackPos
<= 15) {
232 fp_stored2(&copies
[0].d
);
235 fp_stored4(&copies
[1].d
);
238 fp_stored6(&copies
[2].d
);
241 fp_stored8(&copies
[3].d
);
244 fp_stored10(&copies
[4].d
);
247 fp_stored12(&copies
[5].d
);
250 fp_stored14(&copies
[6].d
);
253 fp_stored16(&copies
[7].d
);
256 fp_stored18(&copies
[8].d
);
259 fp_stored20(&copies
[9].d
);
262 fp_stored22(&copies
[10].d
);
265 fp_stored24(&copies
[11].d
);
268 fp_stored26(&copies
[12].d
);
271 fp_stored28(&copies
[13].d
);
274 fp_stored30(&copies
[14].d
);
280 args
[i
] = &copies
[stackPos
- 1].d
;
282 args
[i
] = reinterpret_cast< char * >(callStack
+ stackPos
) +
283 (sizeof (unsigned long) - sizeof (double));
287 OSL_ASSERT(ptd
->nSize
<= 8);
288 args
[i
] = reinterpret_cast< char * >(callStack
+ stackPos
) +
289 (sizeof (unsigned long) - ptd
->nSize
);
293 TYPELIB_DANGER_RELEASE(ptd
);
295 cppArgs
[i
] = reinterpret_cast< void * >(callStack
[stackPos
]);
296 if (!parameters
[i
].bIn
) {
297 args
[i
] = alloca(ptd
->nSize
);
299 } else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd
)) {
300 args
[i
] = alloca(ptd
->nSize
);
301 uno_copyAndConvertData(
302 args
[i
], reinterpret_cast< void * >(callStack
[stackPos
]),
303 ptd
, proxy
->getBridge()->getCpp2Uno());
306 args
[i
] = reinterpret_cast< void * >(callStack
[stackPos
]);
308 TYPELIB_DANGER_RELEASE(ptd
);
314 uno_Any
* pexc
= &exc
;
315 proxy
->getUnoI()->pDispatcher(
316 proxy
->getUnoI(), description
.get(), retin
, args
, &pexc
);
318 for (sal_Int32 i
= 0; i
< count
; ++i
) {
319 if (argtds
[i
] != NULL
) {
320 if (parameters
[i
].bIn
) {
321 uno_destructData(args
[i
], argtds
[i
], NULL
);
323 TYPELIB_DANGER_RELEASE(argtds
[i
]);
327 TYPELIB_DANGER_RELEASE(rtd
);
329 bridges::cpp_uno::cc5_solaris_sparc64::raiseException(
330 &exc
, proxy
->getBridge()->getUno2Cpp());
331 std::abort(); // just in case
333 for (sal_Int32 i
= 0; i
< count
; ++i
) {
334 if (argtds
[i
] != NULL
) {
335 if (parameters
[i
].bOut
) {
337 cppArgs
[i
], argtds
[i
],
338 reinterpret_cast< uno_ReleaseFunc
>(css::uno::cpp_release
));
339 uno_copyAndConvertData(
340 cppArgs
[i
], args
[i
], argtds
[i
],
341 proxy
->getBridge()->getUno2Cpp());
343 uno_destructData(args
[i
], argtds
[i
], NULL
);
344 TYPELIB_DANGER_RELEASE(argtds
[i
]);
349 switch (rtd
->eTypeClass
) {
350 case typelib_TypeClass_VOID
:
352 case typelib_TypeClass_BOOLEAN
:
353 callStack
[0] = *reinterpret_cast< sal_Bool
* >(retbuf
);
355 case typelib_TypeClass_BYTE
:
356 callStack
[0] = *reinterpret_cast< sal_Int8
* >(retbuf
);
358 case typelib_TypeClass_SHORT
:
359 callStack
[0] = *reinterpret_cast< sal_Int16
* >(retbuf
);
361 case typelib_TypeClass_UNSIGNED_SHORT
:
362 callStack
[0] = *reinterpret_cast< sal_uInt16
* >(retbuf
);
364 case typelib_TypeClass_LONG
:
365 case typelib_TypeClass_ENUM
:
366 callStack
[0] = *reinterpret_cast< sal_Int32
* >(retbuf
);
368 case typelib_TypeClass_UNSIGNED_LONG
:
369 callStack
[0] = *reinterpret_cast< sal_uInt32
* >(retbuf
);
371 case typelib_TypeClass_HYPER
:
372 callStack
[0] = *reinterpret_cast< sal_Int64
* >(retbuf
);
374 case typelib_TypeClass_UNSIGNED_HYPER
:
375 callStack
[0] = *reinterpret_cast< sal_uInt64
* >(retbuf
);
377 case typelib_TypeClass_FLOAT
:
378 fp_loadf0(reinterpret_cast< float * >(retbuf
));
380 case typelib_TypeClass_DOUBLE
:
381 fp_loadd0(reinterpret_cast< double * >(retbuf
));
383 case typelib_TypeClass_CHAR
:
384 callStack
[0] = *reinterpret_cast< sal_Unicode
* >(retbuf
);
386 case typelib_TypeClass_STRING
:
387 case typelib_TypeClass_TYPE
:
388 case typelib_TypeClass_SEQUENCE
:
389 case typelib_TypeClass_INTERFACE
:
390 callStack
[0] = reinterpret_cast< unsigned long >(
391 *reinterpret_cast< void ** >(retbuf
));
393 case typelib_TypeClass_STRUCT
:
394 loadFpRegsFromStruct(rtd
, retbuf
);
396 case typelib_TypeClass_ANY
:
397 std::memcpy(callStack
, retbuf
, rtd
->nSize
);
404 } else if (retconv
) {
405 uno_copyAndConvertData(
406 retout
, retin
, rtd
, proxy
->getBridge()->getUno2Cpp());
407 uno_destructData(retin
, rtd
, NULL
);
410 TYPELIB_DANGER_RELEASE(rtd
);
414 extern "C" void vtableCall(
415 sal_Int32 functionIndex
, sal_Int32 vtableOffset
, unsigned long * callStack
)
417 bool direct
= static_cast< sal_uInt32
>((functionIndex
) & 0x80000000) == 0;
418 functionIndex
= static_cast< sal_uInt32
>(functionIndex
) & 0x7FFFFFFF;
419 bridges::cpp_uno::shared::CppInterfaceProxy
* proxy
420 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
421 reinterpret_cast< char * >(callStack
[direct
? 0 : 1]) -
423 typelib_InterfaceTypeDescription
* type
= proxy
->getTypeDescr();
424 OSL_ASSERT(functionIndex
< type
->nMapFunctionIndexToMemberIndex
);
425 sal_Int32 pos
= type
->pMapFunctionIndexToMemberIndex
[functionIndex
];
426 css::uno::TypeDescription
desc(type
->ppAllMembers
[pos
]);
427 switch (desc
.get()->eTypeClass
) {
428 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
429 if (type
->pMapMemberIndexToFunctionIndex
[pos
] == functionIndex
) {
433 reinterpret_cast< typelib_InterfaceAttributeTypeDescription
* >(
434 desc
.get())->pAttributeTypeRef
,
438 typelib_MethodParameter param
= {
440 reinterpret_cast< typelib_InterfaceAttributeTypeDescription
* >(
441 desc
.get())->pAttributeTypeRef
,
443 call(proxy
, desc
, true, NULL
, 1, ¶m
, callStack
);
446 case typelib_TypeClass_INTERFACE_METHOD
:
447 switch (functionIndex
) {
449 proxy
->acquireProxy();
452 proxy
->releaseProxy();
456 typelib_TypeDescription
* td
= NULL
;
459 reinterpret_cast< css::uno::Type
* >(
460 callStack
[2])->getTypeLibType());
462 css::uno::XInterface
* ifc
= NULL
;
463 proxy
->getBridge()->getCppEnv()->getRegisteredInterface(
464 proxy
->getBridge()->getCppEnv(),
465 reinterpret_cast< void ** >(&ifc
),
466 proxy
->getOid().pData
,
467 reinterpret_cast< typelib_InterfaceTypeDescription
* >(
471 reinterpret_cast< uno_Any
* >(callStack
[0]), &ifc
,
473 reinterpret_cast< uno_AcquireFunc
>(
474 css::uno::cpp_acquire
));
476 TYPELIB_DANGER_RELEASE(td
);
479 TYPELIB_DANGER_RELEASE(td
);
485 reinterpret_cast< typelib_InterfaceMethodTypeDescription
* >(
486 desc
.get())->pReturnTypeRef
,
487 reinterpret_cast< typelib_InterfaceMethodTypeDescription
* >(
488 desc
.get())->nParams
,
489 reinterpret_cast< typelib_InterfaceMethodTypeDescription
* >(
490 desc
.get())->pParams
,
500 int const codeSnippetSize
= 10 * 4;
502 unsigned char * generateCodeSnippet(
503 unsigned char * code
, sal_Int32 functionIndex
, sal_Int32 vtableOffset
,
506 sal_uInt32 index
= functionIndex
;
510 unsigned int * p
= reinterpret_cast< unsigned int * >(code
);
511 OSL_ASSERT(sizeof (unsigned int) == 4);
512 // 0*4: save %sp, -176, %sp ! minimal stack frame:
516 // 2*4: ldx %l0, (8-1)*4, %l0:
518 // 3*4: sethi %hi(index), %o0:
519 *p
++ = 0x11000000 | (index
>> 10);
520 // 4*4: or %o0, %lo(index), %o0:
521 *p
++ = 0x90122000 | (index
& 0x3FF);
522 // 5*4: sethi %hi(vtableOffset), %o1:
523 *p
++ = 0x13000000 | (vtableOffset
>> 10);
524 // 6*4: jmpl %l0, %g0, %g0:
526 // 7*4: or %o1, %lo(vtableOffset), %o1:
527 *p
++ = 0x92126000 | (vtableOffset
& 0x3FF);
528 // 8*4: .xword privateSnippetExecutor:
529 *reinterpret_cast< unsigned long * >(p
) =
530 reinterpret_cast< unsigned long >(vtableSlotCall
);
531 return code
+ codeSnippetSize
;
536 struct bridges::cpp_uno::shared::VtableFactory::Slot
{ void * fn
; };
538 bridges::cpp_uno::shared::VtableFactory::Slot
*
539 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block
) {
540 return static_cast< Slot
* >(block
) + 1;
543 sal_Size
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
546 return (slotCount
+ 3) * sizeof (Slot
) + slotCount
* codeSnippetSize
;
549 bridges::cpp_uno::shared::VtableFactory::Slot
*
550 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
551 void * block
, sal_Int32 slotCount
)
553 Slot
* slots
= mapBlockToVtable(block
) + 2;
554 slots
[-3].fn
= NULL
; // RTTI
555 slots
[-2].fn
= NULL
; // null
556 slots
[-1].fn
= NULL
; // destructor
557 return slots
+ slotCount
;
560 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
561 Slot
** slots
, unsigned char * code
,
562 typelib_InterfaceTypeDescription
const * type
, sal_Int32 functionOffset
,
563 sal_Int32 functionCount
, sal_Int32 vtableOffset
)
565 (*slots
) -= functionCount
;
567 for (sal_Int32 i
= 0; i
< type
->nMembers
; ++i
) {
568 typelib_TypeDescription
* member
= 0;
569 TYPELIB_DANGER_GET(&member
, type
->ppMembers
[i
]);
570 OSL_ASSERT(member
!= 0);
571 switch (member
->eTypeClass
) {
572 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
575 code
= generateCodeSnippet(
576 code
, functionOffset
++, vtableOffset
,
577 bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType(
579 typelib_InterfaceAttributeTypeDescription
* >(
580 member
)->pAttributeTypeRef
));
582 if (!reinterpret_cast<
583 typelib_InterfaceAttributeTypeDescription
* >(
587 code
= generateCodeSnippet(
588 code
, functionOffset
++, vtableOffset
, true);
592 case typelib_TypeClass_INTERFACE_METHOD
:
594 code
= generateCodeSnippet(
595 code
, functionOffset
++, vtableOffset
,
596 bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType(
598 typelib_InterfaceMethodTypeDescription
* >(
599 member
)->pReturnTypeRef
));
606 TYPELIB_DANGER_RELEASE(member
);
611 void bridges::cpp_uno::shared::VtableFactory::flushCode(
612 unsigned char const * begin
, unsigned char const * end
)
614 bridges::cpp_uno::cc5_solaris_sparc64::flushCode(begin
, end
);