LibreOffice Module bridges (master) 1
gcc3_ios/cpp2uno.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19#include <com/sun/star/uno/RuntimeException.hpp>
20#include <sal/log.hxx>
21#include <uno/data.h>
22#include <typelib/typedescription.hxx>
23#include "bridge.hxx"
24#include "cppinterfaceproxy.hxx"
25#include "types.hxx"
26#include "vtablefactory.hxx"
27#include "share.hxx"
28
29
30
31extern "C" int codeSnippets[];
32const int nFunIndexes = 8;
33const int nVtableOffsets = 4;
34
35
36
37using namespace ::com::sun::star::uno;
38
39namespace
40{
41 static typelib_TypeClass cpp2uno_call(
43 const typelib_TypeDescription * pMemberTypeDescr,
44 typelib_TypeDescriptionReference * pReturnTypeRef,
45 sal_Int32 nParams,
46 typelib_MethodParameter * pParams,
47 void ** pCallStack,
48 sal_Int64 * pRegisterReturn /* space for register return */ )
49 {
50 // pCallStack: x8, lr, d0..d7, x0..x7, rest of params originally on stack
51 char *pTopStack = (char *)pCallStack;
52 char *pFloatRegs = pTopStack + 2;
53 char *pGPRegs = pTopStack + (2+8)*8;
54 char *pStackedArgs = pTopStack + (2+8+8)*8;
55
56 int nGPR = 0;
57 int nFPR = 0;
58
59 // return
60 typelib_TypeDescription * pReturnTypeDescr = 0;
61 if (pReturnTypeRef)
62 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
63
64 void * pUnoReturn = 0;
65 // complex return ptr: if != 0 && != pUnoReturn, reconversion need
66 void * pCppReturn = 0;
67
68 if (pReturnTypeDescr)
69 {
70 if (!arm::return_in_x8(pReturnTypeRef))
71 pUnoReturn = pRegisterReturn; // direct way for simple types
72 else // complex return via x8
73 {
74 pCppReturn = pCallStack[0];
75
77 pReturnTypeDescr )
78 ? alloca( pReturnTypeDescr->nSize )
79 : pCppReturn); // direct way
80 }
81 }
82
83 // Skip 'this'
84 pGPRegs += 8;
85 nGPR++;
86
87 // Parameters
88 void ** pUnoArgs = (void **)alloca( sizeof(void *) * nParams );
89 void ** pCppArgs = (void **)alloca( sizeof(void *) * nParams );
90
91 // Indices of values this have to be converted (interface conversion
92 // cpp<=>uno)
93 int * pTempIndices = (sal_Int32 *)alloca( sizeof(int) * nParams);
94
95 // Type descriptions for reconversions
96 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)alloca( sizeof(typelib_TypeDescription *) * nParams);
97
98 int nTempIndices = 0;
99
100 for ( int nPos = 0; nPos < nParams; ++nPos )
101 {
102 const typelib_MethodParameter & rParam = pParams[nPos];
103 typelib_TypeDescription * pParamTypeDescr = 0;
104 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
105
106 if (!rParam.bOut &&
108 {
109 if (nFPR < 8 && (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT ||
110 pParamTypeDescr->eTypeClass == typelib_TypeClass_DOUBLE))
111 {
112 pCppArgs[nPos] = pUnoArgs[nPos] = pFloatRegs;
113 pFloatRegs += 8;
114 nFPR++;
115 }
116 else if (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT)
117 {
118 if ((pStackedArgs - pTopStack) % 4)
119 pStackedArgs += 4 - ((pStackedArgs - pTopStack) % 4);
120 pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs;
121 pStackedArgs += 4;
122 }
123 else if (pParamTypeDescr->eTypeClass == typelib_TypeClass_DOUBLE)
124 {
125 if ((pStackedArgs - pTopStack) % 8)
126 pStackedArgs += 8 - ((pStackedArgs - pTopStack) % 8);
127 pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs;
128 pStackedArgs += 8;
129 }
130 else if (nGPR < 8)
131 {
132 pCppArgs[nPos] = pUnoArgs[nPos] = pGPRegs;
133 pGPRegs += 8;
134 nGPR++;
135 }
136 else
137 switch (pParamTypeDescr->eTypeClass)
138 {
139 case typelib_TypeClass_HYPER:
140 case typelib_TypeClass_UNSIGNED_HYPER:
141 if ((pStackedArgs - pTopStack) % 8)
142 pStackedArgs += 8 - ((pStackedArgs - pTopStack) % 8);
143 pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs;
144 pStackedArgs += 8;
145 break;
146 case typelib_TypeClass_ENUM:
147 case typelib_TypeClass_LONG:
148 case typelib_TypeClass_UNSIGNED_LONG:
149 if ((pStackedArgs - pTopStack) % 4)
150 pStackedArgs += 4 - ((pStackedArgs - pTopStack) % 4);
151 pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs;
152 pStackedArgs += 4;
153 break;
154 case typelib_TypeClass_CHAR:
155 case typelib_TypeClass_SHORT:
156 case typelib_TypeClass_UNSIGNED_SHORT:
157 if ((pStackedArgs - pTopStack) % 2)
158 pStackedArgs += 1;
159 pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs;
160 pStackedArgs += 2;
161 break;
162 case typelib_TypeClass_BOOLEAN:
163 case typelib_TypeClass_BYTE:
164 pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs;
165 pStackedArgs += 1;
166 break;
167 default:
168 assert(!"should not happen");
169 break;
170 }
171 // no longer needed
172 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
173 }
174 else // ptr to complex value | ref
175 {
176 if (nGPR < 8)
177 {
178 pCppArgs[nPos] = *(void **)pGPRegs;
179 pGPRegs += 8;
180 }
181 else
182 {
183 if ((pStackedArgs - pTopStack) % 8)
184 pStackedArgs += 8 - ((pStackedArgs - pTopStack) % 8);
185 pCppArgs[nPos] = pStackedArgs;
186 pStackedArgs += 8;
187 }
188
189 if (! rParam.bIn) // is pure out
190 {
191 // uno out is unconstructed mem!
192 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
193 pTempIndices[nTempIndices] = nPos;
194 // will be released at reconversion
195 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
196 }
197 // is in/inout
198 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
199 {
200 uno_copyAndConvertData( pUnoArgs[nPos] =
201 alloca( pParamTypeDescr->nSize ),
202 pCppArgs[nPos], pParamTypeDescr,
203 pThis->getBridge()->getCpp2Uno() );
204 pTempIndices[nTempIndices] = nPos; // has to be reconverted
205 // will be released at reconversion
206 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
207 }
208 else // direct way
209 {
210 pUnoArgs[nPos] = pCppArgs[nPos];
211 // no longer needed
212 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
213 }
214 }
215 }
216
217 // ExceptionHolder
218 uno_Any aUnoExc; // Any will be constructed by callee
219 uno_Any * pUnoExc = &aUnoExc;
220
221 // invoke uno dispatch call
222 (*pThis->getUnoI()->pDispatcher)(
223 pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
224
225 // in case an exception occurred...
226 if (pUnoExc)
227 {
228 // destruct temporary in/inout params
229 for ( ; nTempIndices--; )
230 {
231 int nIndex = pTempIndices[nTempIndices];
232
233 if (pParams[nIndex].bIn) // is in/inout => was constructed
234 uno_destructData( pUnoArgs[nIndex],
235 ppTempParamTypeDescr[nTempIndices], 0 );
236 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
237 }
238 if (pReturnTypeDescr)
239 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
240
242 pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
243 // is here for dummy
244 return typelib_TypeClass_VOID;
245 }
246 else // else no exception occurred...
247 {
248 // temporary params
249 for ( ; nTempIndices--; )
250 {
251 int nIndex = pTempIndices[nTempIndices];
252 typelib_TypeDescription * pParamTypeDescr =
253 ppTempParamTypeDescr[nTempIndices];
254
255 if (pParams[nIndex].bOut) // inout/out
256 {
257 // convert and assign
258 uno_destructData( pCppArgs[nIndex], pParamTypeDescr,
259 cpp_release );
260 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex],
261 pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
262 }
263 // destroy temp uno param
264 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
265
266 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
267 }
268 // return
269 if (pCppReturn) // has complex return
270 {
271 if (pUnoReturn != pCppReturn) // needs reconversion
272 {
273 uno_copyAndConvertData( pCppReturn, pUnoReturn,
274 pReturnTypeDescr, pThis->getBridge()->getUno2Cpp() );
275 // destroy temp uno return
276 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
277 }
278 *(void **)pRegisterReturn = pCppReturn;
279 }
280 if (pReturnTypeDescr)
281 {
282 typelib_TypeClass eRet =
283 (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
284 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
285 return eRet;
286 }
287 else
288 return typelib_TypeClass_VOID;
289 }
290 }
291
292
293 static void cpp_mediate(sal_Int32 nFunctionIndex,
294 sal_Int32 nVtableOffset,
295 void ** pCallStack)
296 {
297 sal_Int64 nRegReturn;
298 sal_Int64 *pRegisterReturn = &nRegReturn;
299
300 // pCallStack: x8, lr, d0..d7, x0..x7, rest of params originally on stack
301 // _this_ ptr is patched cppu_XInterfaceProxy object
302 void *pThis = pCallStack[2 + 8];
303
304 pThis = static_cast< char * >(pThis) - nVtableOffset;
307 pThis);
308
309 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
310
311 // determine called method
312 assert( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex );
313
314 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
315 {
316 throw RuntimeException( "illegal vtable index!", (XInterface *)pCppI );
317 }
318
319 sal_Int32 nMemberPos =
320 pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
321 assert( nMemberPos < pTypeDescr->nAllMembers );
322
323 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
324
325 typelib_TypeClass eRet;
326 switch (aMemberDescr.get()->eTypeClass)
327 {
328 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
329 {
330 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] ==
331 nFunctionIndex)
332 {
333 // is GET method
334 eRet = cpp2uno_call(
335 pCppI, aMemberDescr.get(),
336 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
337 0, 0, // no params
338 pCallStack, pRegisterReturn );
339 }
340 else
341 {
342 // is SET method
343 typelib_MethodParameter aParam;
344 aParam.pTypeRef =
345 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
346 aParam.bIn = sal_True;
347 aParam.bOut = sal_False;
348
349 eRet = cpp2uno_call(
350 pCppI, aMemberDescr.get(),
351 0, // indicates void return
352 1, &aParam,
353 pCallStack, pRegisterReturn );
354 }
355 break;
356 }
357 case typelib_TypeClass_INTERFACE_METHOD:
358 {
359 // is METHOD
360 switch (nFunctionIndex)
361 {
362 case 1: // acquire()
363 pCppI->acquireProxy(); // non virtual call!
364 eRet = typelib_TypeClass_VOID;
365 break;
366 case 2: // release()
367 pCppI->releaseProxy(); // non virtual call!
368 eRet = typelib_TypeClass_VOID;
369 break;
370 case 0: // queryInterface() opt
371 {
372 typelib_TypeDescription * pTD = 0;
373 TYPELIB_DANGER_GET(&pTD,
374 reinterpret_cast<Type *>(pCallStack[2])->getTypeLibType());
375 if (pTD)
376 {
377 XInterface * pInterface = 0;
378 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
379 pCppI->getBridge()->getCppEnv(),
380 (void **)&pInterface, pCppI->getOid().pData,
381 (typelib_InterfaceTypeDescription *)pTD );
382
383 if (pInterface)
384 {
385 ::uno_any_construct(
386 reinterpret_cast< uno_Any * >( pCallStack[0] ),
387 &pInterface, pTD, cpp_acquire );
388 pInterface->release();
389 TYPELIB_DANGER_RELEASE( pTD );
390 *(void **)pRegisterReturn = pCallStack[0];
391 eRet = typelib_TypeClass_ANY;
392 break;
393 }
394 TYPELIB_DANGER_RELEASE( pTD );
395 }
396 } // else perform queryInterface()
397 [[fallthrough]];
398 default:
399 eRet = cpp2uno_call(
400 pCppI, aMemberDescr.get(),
401 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
402 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
403 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
404 pCallStack, pRegisterReturn );
405 }
406 break;
407 }
408 default:
409 {
410 throw RuntimeException( "no member description found!", (XInterface *)pCppI );
411 }
412 }
413
414 (void)eRet;
415 return;
416 }
417}
418
424extern "C" void cpp_vtable_call( sal_Int32 func, sal_Int32 offset,
425 void **pStack )
426{
427 cpp_mediate(func, offset, pStack);
428}
429
430namespace
431{
432 unsigned char *codeSnippet(const typelib_InterfaceTypeDescription *type,
433 const typelib_TypeDescription *member,
434 sal_Int32 functionIndex,
435 sal_Int32 vtableOffset)
436 {
437 // For now temporarily assert when we get here. The intent is
438 // that we won't need the code snippets at all on iOS.
439 assert(false);
440
441 assert(functionIndex < nFunIndexes);
442 if (!(functionIndex < nFunIndexes))
443 return NULL;
444
445 assert(vtableOffset < nVtableOffsets);
446 if (!(vtableOffset < nVtableOffsets))
447 return NULL;
448
449 // The codeSnippets table is indexed by functionIndex and vtableOffset
450
451 int index = functionIndex*nVtableOffsets + vtableOffset;
452 unsigned char *result = ((unsigned char *) &codeSnippets) + codeSnippets[index];
453
454 SAL_INFO( "bridges", "codeSnippet(" << OUString(type->aBase.pTypeName) << "::" << OUString(member->pTypeName) << "): [" << functionIndex << "," << vtableOffset << "]=" << (void *) result << " (" << std::hex << ((int*)result)[0] << "," << ((int*)result)[1] << "," << ((int*)result)[2] << "," << ((int*)result)[3] << ")");
455
456 return result;
457 }
458}
459
461
464{
465 return static_cast< Slot * >(block) + 2;
466}
467
469 sal_Int32 slotCount)
470{
471 return (slotCount + 2) * sizeof (Slot);
472}
473
476 void * block, sal_Int32 slotCount, sal_Int32,
477 typelib_InterfaceTypeDescription *)
478{
479 Slot * slots = mapBlockToVtable(block);
480 slots[-2].fn = 0;
481 slots[-1].fn = 0;
482 return slots + slotCount;
483}
484
486 Slot ** slots,
487 unsigned char * code,
488 typelib_InterfaceTypeDescription const * type,
489 sal_Int32 functionOffset,
490 sal_Int32 functionCount,
491 sal_Int32 vtableOffset)
492{
493 (*slots) -= functionCount;
494 Slot * s = *slots;
495 for (sal_Int32 i = 0; i < type->nMembers; ++i)
496 {
497 typelib_TypeDescription * member = 0;
498 TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
499 assert(member != 0);
500 switch (member->eTypeClass)
501 {
502 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
503 {
504 typelib_InterfaceAttributeTypeDescription *pAttrTD =
505 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( member );
506
507 // Getter:
508 (s++)->fn = codeSnippet( type, member, functionOffset++, vtableOffset );
509
510 // Setter:
511 if (!pAttrTD->bReadOnly)
512 {
513 (s++)->fn = codeSnippet( type, member, functionOffset++, vtableOffset );
514 }
515 break;
516 }
517 case typelib_TypeClass_INTERFACE_METHOD:
518 {
519 (s++)->fn = codeSnippet( type, member, functionOffset++, vtableOffset );
520 break;
521 }
522 default:
523 assert(false);
524 break;
525 }
526 TYPELIB_DANGER_RELEASE(member);
527 }
528 return code;
529}
530
531
532
534 unsigned char const *, unsigned char const *)
535{
536 // No dynamic code generation so nothing to flush
537}
538
539
540/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
uno_Mapping * getUno2Cpp()
Definition: bridge.hxx:73
uno_ExtEnvironment * getCppEnv()
Definition: bridge.hxx:69
uno_Mapping * getCpp2Uno()
Definition: bridge.hxx:72
A cpp proxy wrapping a uno interface.
static CppInterfaceProxy * castInterfaceToProxy(void *pInterface)
typelib_InterfaceTypeDescription * getTypeDescr()
static Slot * mapBlockToVtable(void *block)
Given a pointer to a block, turn it into a vtable pointer.
static void flushCode(unsigned char const *begin, unsigned char const *end)
Flush all the generated code snippets of a vtable, on platforms that require it.
static unsigned char * addLocalFunctions(Slot **slots, unsigned char *code, sal_PtrDiff writetoexecdiff, typelib_InterfaceTypeDescription const *type, sal_Int32 functionOffset, sal_Int32 functionCount, sal_Int32 vtableOffset)
Fill the vtable slots corresponding to all local (i.e., not inherited) functions of a given interface...
static Slot * initializeBlock(void *block, sal_Int32 slotCount, sal_Int32 vtableNumber, typelib_InterfaceTypeDescription *type)
Initialize a raw vtable block.
static std::size_t getBlockSize(sal_Int32 slotCount)
Calculate the size of a raw vtable block.
void SAL_CALL uno_destructData(void *pValue, typelib_TypeDescription *pTypeDescr, uno_ReleaseFunc release) SAL_THROW_EXTERN_C()
void SAL_CALL uno_copyAndConvertData(void *pDest, void *pSource, typelib_TypeDescription *pTypeDescr, uno_Mapping *mapping) SAL_THROW_EXTERN_C()
const int nVtableOffsets
int codeSnippets[]
const int nFunIndexes
void cpp_vtable_call(sal_Int32 func, sal_Int32 offset, void **pStack)
is called on incoming vtable calls (called by asm snippets)
static unsigned char * codeSnippet(unsigned char *code, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, bool bHasHiddenParam)
static int cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy *pThis, const typelib_TypeDescription *pMemberTypeDescr, typelib_TypeDescriptionReference *pReturnTypeRef, sal_Int32 nParams, typelib_MethodParameter *pParams, void **gpreg, void **fpreg, void **ovrflw, sal_uInt64 *pRegisterReturn)
sal_Int32 nIndex
sal_uInt16 nPos
#define SAL_INFO(area, stream)
return NULL
struct _typelib_TypeDescription typelib_TypeDescription
Definition: msvc/except.hxx:52
struct _uno_Any uno_Any
Definition: msvc/except.hxx:31
typelib_TypeClass __cdecl cpp_mediate(void **pCallStack, const sal_Int32 nFunctionIndex, const sal_Int32 nVtableOffset, sal_Int64 *const pRegisterReturn)
void raiseException(uno_Any *pUnoExc, uno_Mapping *pUno2Cpp)
bool return_in_x8(typelib_TypeDescriptionReference *pTypeRef)
bool isSimpleType(typelib_TypeClass typeClass)
Determines whether a type is a "simple" type (VOID, BOOLEAN, BYTE, SHORT, UNSIGNED SHORT,...
Definition: types.cxx:28
bool relatesToInterfaceType(typelib_TypeDescription const *type)
Determines whether a type relates to an interface type (is itself an interface type,...
Definition: types.cxx:41
Type
int i
index
sal_Unicode code
#define sal_True
#define sal_False
Any result
ResultType type