tdf#121119 master docs at-page anchor: clean-up renaming
[LibreOffice.git] / bridges / source / cpp_uno / gcc3_linux_x86-64 / uno2cpp.cxx
blob8934943622b4e7b156e6bd71f15ad80ed5574640
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <exception>
21 #include <typeinfo>
23 #include <com/sun/star/uno/genfunc.hxx>
24 #include <com/sun/star/uno/RuntimeException.hpp>
25 #include <o3tl/runtimetooustring.hxx>
26 #include <uno/data.h>
28 #include <bridge.hxx>
29 #include <types.hxx>
30 #include <unointerfaceproxy.hxx>
31 #include <vtables.hxx>
33 #include "abi.hxx"
34 #include "callvirtualmethod.hxx"
35 #include "share.hxx"
37 using namespace ::com::sun::star::uno;
39 namespace {
41 // Functions for easier insertion of values to registers or stack
42 // pSV - pointer to the source
43 // nr - order of the value [will be increased if stored to register]
44 // pFPR, pGPR - pointer to the registers
45 // pDS - pointer to the stack [will be increased if stored here]
47 // The value in %xmm register is already prepared to be retrieved as a float,
48 // thus we treat float and double the same
49 void INSERT_FLOAT_DOUBLE(
50 void const * pSV, sal_uInt32 & nr, double * pFPR, sal_uInt64 *& pDS)
52 if ( nr < x86_64::MAX_SSE_REGS )
53 pFPR[nr++] = *static_cast<double const *>( pSV );
54 else
55 *pDS++ = *static_cast<sal_uInt64 const *>( pSV ); // verbatim!
58 void INSERT_INT64(
59 void const * pSV, sal_uInt32 & nr, sal_uInt64 * pGPR, sal_uInt64 *& pDS)
61 if ( nr < x86_64::MAX_GPR_REGS )
62 pGPR[nr++] = *static_cast<sal_uInt64 const *>( pSV );
63 else
64 *pDS++ = *static_cast<sal_uInt64 const *>( pSV );
67 void INSERT_INT32(
68 void const * pSV, sal_uInt32 & nr, sal_uInt64 * pGPR, sal_uInt64 *& pDS)
70 if ( nr < x86_64::MAX_GPR_REGS )
71 pGPR[nr++] = *static_cast<sal_uInt32 const *>( pSV );
72 else
73 *pDS++ = *static_cast<sal_uInt32 const *>( pSV );
76 void INSERT_INT16(
77 void const * pSV, sal_uInt32 & nr, sal_uInt64 * pGPR, sal_uInt64 *& pDS)
79 if ( nr < x86_64::MAX_GPR_REGS )
80 pGPR[nr++] = *static_cast<sal_uInt16 const *>( pSV );
81 else
82 *pDS++ = *static_cast<sal_uInt16 const *>( pSV );
85 void INSERT_INT8(
86 void const * pSV, sal_uInt32 & nr, sal_uInt64 * pGPR, sal_uInt64 *& pDS)
88 if ( nr < x86_64::MAX_GPR_REGS )
89 pGPR[nr++] = *static_cast<sal_uInt8 const *>( pSV );
90 else
91 *pDS++ = *static_cast<sal_uInt8 const *>( pSV );
96 static void cpp_call(
97 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
98 bridges::cpp_uno::shared::VtableSlot aVtableSlot,
99 typelib_TypeDescriptionReference * pReturnTypeRef,
100 sal_Int32 nParams, typelib_MethodParameter * pParams,
101 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
103 // Maximum space for [complex ret ptr], values | ptr ...
104 // (but will be used less - some of the values will be in pGPR and pFPR)
105 sal_uInt64 *pStack = static_cast<sal_uInt64 *>(__builtin_alloca( (nParams + 3) * sizeof(sal_uInt64) ));
106 sal_uInt64 *pStackStart = pStack;
108 sal_uInt64 pGPR[x86_64::MAX_GPR_REGS];
109 sal_uInt32 nGPR = 0;
111 double pFPR[x86_64::MAX_SSE_REGS];
112 sal_uInt32 nFPR = 0;
114 // Return
115 typelib_TypeDescription * pReturnTypeDescr = nullptr;
116 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
117 assert(pReturnTypeDescr);
119 void * pCppReturn = nullptr; // if != 0 && != pUnoReturn, needs reconversion (see below)
121 bool bSimpleReturn = true;
122 if ( pReturnTypeDescr )
124 if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
125 bSimpleReturn = false;
127 if ( bSimpleReturn )
128 pCppReturn = pUnoReturn; // direct way for simple types
129 else
131 // complex return via ptr
132 pCppReturn = bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )?
133 __builtin_alloca( pReturnTypeDescr->nSize ) : pUnoReturn;
134 INSERT_INT64( &pCppReturn, nGPR, pGPR, pStack );
138 // Push "this" pointer
139 void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
140 INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack );
142 // Args
143 void ** pCppArgs = static_cast<void **>(alloca( 3 * sizeof(void *) * nParams ));
144 // Indices of values this have to be converted (interface conversion cpp<=>uno)
145 sal_Int32 * pTempIndices = reinterpret_cast<sal_Int32 *>(pCppArgs + nParams);
146 // Type descriptions for reconversions
147 typelib_TypeDescription ** ppTempParamTypeDescr = reinterpret_cast<typelib_TypeDescription **>(pCppArgs + (2 * nParams));
149 sal_Int32 nTempIndices = 0;
151 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
153 const typelib_MethodParameter & rParam = pParams[nPos];
154 typelib_TypeDescription * pParamTypeDescr = nullptr;
155 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
157 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
159 pCppArgs[nPos] = alloca( 8 );
160 uno_copyAndConvertData( pCppArgs[nPos], pUnoArgs[nPos], pParamTypeDescr,
161 pThis->getBridge()->getUno2Cpp() );
163 switch (pParamTypeDescr->eTypeClass)
165 case typelib_TypeClass_HYPER:
166 case typelib_TypeClass_UNSIGNED_HYPER:
167 INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack );
168 break;
169 case typelib_TypeClass_LONG:
170 case typelib_TypeClass_UNSIGNED_LONG:
171 case typelib_TypeClass_ENUM:
172 INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack );
173 break;
174 case typelib_TypeClass_SHORT:
175 case typelib_TypeClass_CHAR:
176 case typelib_TypeClass_UNSIGNED_SHORT:
177 INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack );
178 break;
179 case typelib_TypeClass_BOOLEAN:
180 case typelib_TypeClass_BYTE:
181 INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack );
182 break;
183 case typelib_TypeClass_FLOAT:
184 case typelib_TypeClass_DOUBLE:
185 INSERT_FLOAT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, pStack );
186 break;
187 default:
188 break;
191 // no longer needed
192 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
194 else // ptr to complex value | ref
196 if (! rParam.bIn) // is pure out
198 // cpp out is constructed mem, uno out is not!
199 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize );
200 uno_constructData( pCppArgs[nPos], pParamTypeDescr );
201 pTempIndices[nTempIndices] = nPos; // default constructed for cpp call
202 // will be released at reconversion
203 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
205 // is in/inout
206 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
208 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize );
209 uno_copyAndConvertData(
210 pCppArgs[nPos], pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
212 pTempIndices[nTempIndices] = nPos; // has to be reconverted
213 // will be released at reconversion
214 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
216 else // direct way
218 pCppArgs[nPos] = pUnoArgs[nPos];
219 // no longer needed
220 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
222 INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack );
228 try {
229 CPPU_CURRENT_NAMESPACE::callVirtualMethod(
230 pAdjustedThisPtr, aVtableSlot.index,
231 pCppReturn, pReturnTypeRef, bSimpleReturn,
232 pStackStart, ( pStack - pStackStart ),
233 pGPR, pFPR );
234 } catch (const Exception &) {
235 throw;
236 } catch (const std::exception & e) {
237 throw RuntimeException(
238 "C++ code threw " + o3tl::runtimeToOUString(typeid(e).name())
239 + ": " + o3tl::runtimeToOUString(e.what()));
240 } catch (...) {
241 throw RuntimeException(u"C++ code threw unknown exception"_ustr);
244 *ppUnoExc = nullptr;
246 // reconvert temporary params
247 for ( ; nTempIndices--; )
249 sal_Int32 nIndex = pTempIndices[nTempIndices];
250 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
252 if (pParams[nIndex].bIn)
254 if (pParams[nIndex].bOut) // inout
256 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, nullptr ); // destroy uno value
257 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
258 pThis->getBridge()->getCpp2Uno() );
261 else // pure out
263 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
264 pThis->getBridge()->getCpp2Uno() );
266 // destroy temp cpp param => cpp: every param was constructed
267 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
269 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
271 // return value
272 if (pCppReturn && pUnoReturn != pCppReturn)
274 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
275 pThis->getBridge()->getCpp2Uno() );
276 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
279 catch (...)
281 // fill uno exception
282 CPPU_CURRENT_NAMESPACE::fillUnoException(*ppUnoExc, pThis->getBridge()->getCpp2Uno());
284 // temporary params
285 for ( ; nTempIndices--; )
287 sal_Int32 nIndex = pTempIndices[nTempIndices];
288 // destroy temp cpp param => cpp: every param was constructed
289 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndices], cpp_release );
290 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
292 // return type
293 if (pReturnTypeDescr)
294 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
299 namespace bridges::cpp_uno::shared {
301 void unoInterfaceProxyDispatch(
302 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
303 void * pReturn, void * pArgs[], uno_Any ** ppException )
305 // is my surrogate
306 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
307 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
309 switch (pMemberDescr->eTypeClass)
311 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
313 assert(
314 (reinterpret_cast<typelib_InterfaceMemberTypeDescription const *>(pMemberDescr)
315 ->nPosition)
316 < pThis->pTypeDescr->nAllMembers);
317 VtableSlot aVtableSlot(
318 getVtableSlot(
319 reinterpret_cast<
320 typelib_InterfaceAttributeTypeDescription const * >(
321 pMemberDescr)));
323 if (pReturn)
325 // dependent dispatch
326 cpp_call(
327 pThis, aVtableSlot,
328 reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(pMemberDescr)->pAttributeTypeRef,
329 0, nullptr, // no params
330 pReturn, pArgs, ppException );
332 else
334 // is SET
335 typelib_MethodParameter aParam;
336 aParam.pTypeRef =
337 reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(pMemberDescr)->pAttributeTypeRef;
338 aParam.bIn = true;
339 aParam.bOut = false;
341 typelib_TypeDescriptionReference * pReturnTypeRef = nullptr;
342 OUString aVoidName(u"void"_ustr);
343 typelib_typedescriptionreference_new(
344 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
346 // dependent dispatch
347 aVtableSlot.index += 1; // get, then set method
348 cpp_call(
349 pThis, aVtableSlot, // get, then set method
350 pReturnTypeRef,
351 1, &aParam,
352 pReturn, pArgs, ppException );
354 typelib_typedescriptionreference_release( pReturnTypeRef );
357 break;
359 case typelib_TypeClass_INTERFACE_METHOD:
361 assert(
362 (reinterpret_cast<typelib_InterfaceMemberTypeDescription const *>(pMemberDescr)
363 ->nPosition)
364 < pThis->pTypeDescr->nAllMembers);
365 VtableSlot aVtableSlot(
366 getVtableSlot(
367 reinterpret_cast<
368 typelib_InterfaceMethodTypeDescription const * >(
369 pMemberDescr)));
371 switch (aVtableSlot.index)
373 // standard calls
374 case 1: // acquire uno interface
375 (*pUnoI->acquire)( pUnoI );
376 *ppException = nullptr;
377 break;
378 case 2: // release uno interface
379 (*pUnoI->release)( pUnoI );
380 *ppException = nullptr;
381 break;
382 case 0: // queryInterface() opt
384 typelib_TypeDescription * pTD = nullptr;
385 TYPELIB_DANGER_GET( &pTD, static_cast< Type * >( pArgs[0] )->getTypeLibType() );
386 if (pTD)
388 uno_Interface * pInterface = nullptr;
389 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
390 pThis->getBridge()->getUnoEnv(),
391 reinterpret_cast<void **>(&pInterface), pThis->oid.pData, reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD) );
393 if (pInterface)
395 ::uno_any_construct(
396 static_cast< uno_Any * >( pReturn ),
397 &pInterface, pTD, nullptr );
398 (*pInterface->release)( pInterface );
399 TYPELIB_DANGER_RELEASE( pTD );
400 *ppException = nullptr;
401 break;
403 TYPELIB_DANGER_RELEASE( pTD );
405 [[fallthrough]]; // else perform queryInterface()
407 default:
408 // dependent dispatch
409 cpp_call(
410 pThis, aVtableSlot,
411 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberDescr)->pReturnTypeRef,
412 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberDescr)->nParams,
413 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberDescr)->pParams,
414 pReturn, pArgs, ppException );
416 break;
418 default:
420 ::com::sun::star::uno::RuntimeException aExc(
421 u"illegal member type description!"_ustr,
422 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
424 Type const & rExcType = cppu::UnoType<decltype(aExc)>::get();
425 // binary identical null reference
426 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), nullptr );
433 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */