LibreOffice Module bridges (master) 1
gcc3_linux_aarch64/uno2cpp.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
20#include <sal/config.h>
21
22#include <cassert>
23#include <cstring>
24#include <exception>
25#include <typeinfo>
26
27#include <bridge.hxx>
28#include <types.hxx>
29#include <unointerfaceproxy.hxx>
30#include <vtables.hxx>
31#include <com/sun/star/uno/Exception.hpp>
32#include <com/sun/star/uno/RuntimeException.hpp>
33#include <com/sun/star/uno/genfunc.hxx>
34#include <rtl/textenc.h>
35#include <rtl/ustring.hxx>
36#include <sal/alloca.h>
37#include <sal/types.h>
38#include <typelib/typeclass.h>
39#include <typelib/typedescription.h>
40#include <uno/any2.h>
41#include <uno/data.h>
42
43#include "abi.hxx"
45
46namespace {
47
48void pushArgument(
49#ifdef MACOSX
50 typelib_TypeClass typeclass,
51 sal_Int32 * const subsp,
52#endif
53 unsigned long value, unsigned long * const stack, sal_Int32 * const sp,
54 unsigned long * const regs, sal_Int32 * const nregs)
55{
56#ifdef MACOSX
57 if (*nregs != 8)
58 {
59 regs[(*nregs)++] = value;
60 }
61 else
62 {
63 switch (typeclass) {
64 case typelib_TypeClass_BOOLEAN:
65 case typelib_TypeClass_BYTE:
66 *reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(stack + *sp) + *subsp) = value;
67 (*subsp) += 1;
68 if (*subsp == 8)
69 {
70 (*sp)++;
71 *subsp = 0;
72 }
73 break;
74 case typelib_TypeClass_SHORT:
75 case typelib_TypeClass_UNSIGNED_SHORT:
76 case typelib_TypeClass_CHAR:
77 *subsp = (*subsp + 1) & ~0x1;
78 if (*subsp == 8)
79 {
80 (*sp)++;
81 *subsp = 0;
82 }
83 *reinterpret_cast<uint16_t*>(reinterpret_cast<uintptr_t>(stack + *sp) + *subsp) = value;
84 (*subsp) += 2;
85 if (*subsp == 8)
86 {
87 (*sp)++;
88 *subsp = 0;
89 }
90 break;
91 case typelib_TypeClass_LONG:
92 case typelib_TypeClass_UNSIGNED_LONG:
93 case typelib_TypeClass_ENUM:
94 case typelib_TypeClass_FLOAT:
95 *subsp = (*subsp + 3) & ~0x3;
96 if (*subsp == 8)
97 {
98 (*sp)++;
99 *subsp = 0;
100 }
101 *reinterpret_cast<uint32_t*>(reinterpret_cast<uintptr_t>(stack + *sp) + *subsp) = value;
102 (*subsp) += 4;
103 if (*subsp == 8)
104 {
105 (*sp)++;
106 *subsp = 0;
107 }
108 break;
109 case typelib_TypeClass_HYPER:
110 case typelib_TypeClass_UNSIGNED_HYPER:
111 default:
112 if (*subsp > 0)
113 {
114 (*sp)++;
115 *subsp = 0;
116 }
117 stack[*sp] = value;
118 (*sp)++;
119 break;
120 }
121 }
122#else
123 (*nregs != 8 ? regs[(*nregs)++] : stack[(*sp)++]) = value;
124#endif
125}
126
127void call(
130 typelib_TypeDescriptionReference * returnType, sal_Int32 count,
131 typelib_MethodParameter * parameters, void * returnValue, void ** arguments,
132 uno_Any ** exception)
133{
134 typelib_TypeDescription * rtd = nullptr;
135 TYPELIB_DANGER_GET(&rtd, returnType);
138 void * ret = retConv ? alloca(rtd->nSize) : returnValue;
139 unsigned long ** thisPtr
140 = reinterpret_cast<unsigned long **>(proxy->getCppI()) + slot.offset;
141 unsigned long * stack = static_cast<unsigned long *>(
142 alloca(count * sizeof (unsigned long)));
143 sal_Int32 sp = 0;
144#ifdef MACOSX
145 sal_Int32 subsp = 0;
146#endif
147 unsigned long gpr[8];
148 sal_Int32 ngpr = 0;
149 unsigned long fpr[8];
150 sal_Int32 nfpr = 0;
151 gpr[ngpr++] = reinterpret_cast<unsigned long>(thisPtr);
152 void ** cppArgs = static_cast<void **>(alloca(count * sizeof (void *)));
154 static_cast<typelib_TypeDescription **>(
155 alloca(count * sizeof (typelib_TypeDescription *)));
156 for (sal_Int32 i = 0; i != count; ++i) {
157 if (!parameters[i].bOut &&
158 bridges::cpp_uno::shared::isSimpleType(parameters[i].pTypeRef))
159 {
160 cppArgs[i] = nullptr;
161 switch (parameters[i].pTypeRef->eTypeClass) {
162 case typelib_TypeClass_BOOLEAN:
163 pushArgument(
164#ifdef MACOSX
165 parameters[i].pTypeRef->eTypeClass, &subsp,
166#endif
167 static_cast<unsigned long>(*static_cast<sal_Bool *>(arguments[i])), stack, &sp,
168 gpr, &ngpr);
169 break;
170 case typelib_TypeClass_BYTE:
171 pushArgument(
172#ifdef MACOSX
173 parameters[i].pTypeRef->eTypeClass, &subsp,
174#endif
175 *static_cast<sal_Int8 *>(arguments[i]), stack, &sp, gpr,
176 &ngpr);
177 break;
178 case typelib_TypeClass_SHORT:
179 pushArgument(
180#ifdef MACOSX
181 parameters[i].pTypeRef->eTypeClass, &subsp,
182#endif
183 *static_cast<sal_Int16 *>(arguments[i]), stack, &sp, gpr,
184 &ngpr);
185 break;
186 case typelib_TypeClass_UNSIGNED_SHORT:
187 pushArgument(
188#ifdef MACOSX
189 parameters[i].pTypeRef->eTypeClass, &subsp,
190#endif
191 *static_cast<sal_uInt16 *>(arguments[i]), stack, &sp, gpr,
192 &ngpr);
193 break;
194 case typelib_TypeClass_LONG:
195 case typelib_TypeClass_ENUM:
196 pushArgument(
197#ifdef MACOSX
198 parameters[i].pTypeRef->eTypeClass, &subsp,
199#endif
200 *static_cast<sal_Int32 *>(arguments[i]), stack, &sp, gpr,
201 &ngpr);
202 break;
203 case typelib_TypeClass_UNSIGNED_LONG:
204 pushArgument(
205#ifdef MACOSX
206 parameters[i].pTypeRef->eTypeClass, &subsp,
207#endif
208 *static_cast<sal_uInt32 *>(arguments[i]), stack, &sp, gpr,
209 &ngpr);
210 break;
211 case typelib_TypeClass_HYPER:
212 pushArgument(
213#ifdef MACOSX
214 parameters[i].pTypeRef->eTypeClass, &subsp,
215#endif
216 *static_cast<sal_Int64 *>(arguments[i]), stack, &sp, gpr,
217 &ngpr);
218 break;
219 case typelib_TypeClass_UNSIGNED_HYPER:
220 pushArgument(
221#ifdef MACOSX
222 parameters[i].pTypeRef->eTypeClass, &subsp,
223#endif
224 *static_cast<sal_uInt64 *>(arguments[i]), stack, &sp, gpr,
225 &ngpr);
226 break;
227 case typelib_TypeClass_FLOAT:
228 pushArgument(
229#ifdef MACOSX
230 parameters[i].pTypeRef->eTypeClass, &subsp,
231#endif
232 *static_cast<unsigned int *>(arguments[i]), stack, &sp, fpr,
233 &nfpr);
234 break;
235 case typelib_TypeClass_DOUBLE:
236 pushArgument(
237#ifdef MACOSX
238 parameters[i].pTypeRef->eTypeClass, &subsp,
239#endif
240 *static_cast<unsigned long *>(arguments[i]), stack, &sp,
241 fpr, &nfpr);
242 break;
243 case typelib_TypeClass_CHAR:
244 pushArgument(
245#ifdef MACOSX
246 parameters[i].pTypeRef->eTypeClass, &subsp,
247#endif
248 *static_cast<sal_Unicode *>(arguments[i]), stack, &sp, gpr,
249 &ngpr);
250 break;
251 default:
252 assert(false);
253 }
254 } else {
255 typelib_TypeDescription * ptd = nullptr;
256 TYPELIB_DANGER_GET(&ptd, parameters[i].pTypeRef);
257 if (!parameters[i].bIn) {
258 cppArgs[i] = alloca(ptd->nSize);
259 uno_constructData(cppArgs[i], ptd);
260 ptds[i] = ptd;
261 pushArgument(
262#ifdef MACOSX
263 typelib_TypeClass_HYPER, &subsp,
264#endif
265 reinterpret_cast<unsigned long>(cppArgs[i]), stack, &sp,
266 gpr, &ngpr);
268 cppArgs[i] = alloca(ptd->nSize);
270 cppArgs[i], arguments[i], ptd,
271 proxy->getBridge()->getUno2Cpp());
272 ptds[i] = ptd;
273 pushArgument(
274#ifdef MACOSX
275 typelib_TypeClass_HYPER, &subsp,
276#endif
277 reinterpret_cast<unsigned long>(cppArgs[i]), stack, &sp,
278 gpr, &ngpr);
279 } else {
280 cppArgs[i] = nullptr;
281 pushArgument(
282#ifdef MACOSX
283 typelib_TypeClass_HYPER, &subsp,
284#endif
285 reinterpret_cast<unsigned long>(arguments[i]), stack, &sp,
286 gpr, &ngpr);
287 TYPELIB_DANGER_RELEASE(ptd);
288 }
289 }
290 }
291 try {
292 try {
294 (*thisPtr)[slot.index], gpr, fpr, stack, sp, ret);
295 } catch (css::uno::Exception &) {
296 throw;
297 } catch (std::exception & e) {
298 throw css::uno::RuntimeException(
299 "C++ code threw "
300 + OStringToOUString(typeid(e).name(), RTL_TEXTENCODING_UTF8)
301 + ": " + OStringToOUString(e.what(), RTL_TEXTENCODING_UTF8));
302 } catch (...) {
303 throw css::uno::RuntimeException(
304 "C++ code threw unknown exception");
305 }
306 } catch (css::uno::Exception &) {
308 __cxxabiv1::__cxa_get_globals())->caughtExceptions;
309#if !defined MACOSX && defined _LIBCPPABI_VERSION // detect libc++abi
310 // Very bad HACK to find out whether we run against a libcxxabi that has a new
311 // __cxa_exception::reserved member at the start, introduced with LLVM 10
312 // <https://github.com/llvm/llvm-project/commit/674ec1eb16678b8addc02a4b0534ab383d22fa77>
313 // "[libcxxabi] Insert padding in __cxa_exception struct for compatibility". The layout of
314 // the start of __cxa_exception is
315 //
316 // [8 byte void *reserve]
317 // 8 byte size_t referenceCount
318 //
319 // where the (bad, hacky) assumption is that reserve (if present) is null
320 // (__cxa_allocate_exception in at least LLVM 11 zero-fills the object, and nothing actively
321 // sets reserve) while referenceCount is non-null (__cxa_throw sets it to 1, and
322 // __cxa_decrement_exception_refcount destroys the exception as soon as it drops to 0; for a
323 // __cxa_dependent_exception, the referenceCount member is rather
324 //
325 // 8 byte void* primaryException
326 //
327 // but which also will always be set to a non-null value in
328 // __cxa_rethrow_primary_exception). As described in the definition of __cxa_exception
329 // (bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx), this hack (together with the
330 // "#ifdef MACOSX" there) can be dropped once we can be sure that we only run against new
331 // libcxxabi that has the reserve member:
332 if (*reinterpret_cast<void **>(header) == nullptr) {
333 header = reinterpret_cast<__cxxabiv1::__cxa_exception*>(
334 reinterpret_cast<void **>(header) + 1);
335 }
336#endif
338 header,
340 proxy->getBridge()->getCpp2Uno());
341 for (sal_Int32 i = 0; i != count; ++i) {
342 if (cppArgs[i] != nullptr) {
344 cppArgs[i], ptds[i],
345 reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release));
346 TYPELIB_DANGER_RELEASE(ptds[i]);
347 }
348 }
349 TYPELIB_DANGER_RELEASE(rtd);
350 return;
351 }
352 *exception = nullptr;
353 for (sal_Int32 i = 0; i != count; ++i) {
354 if (cppArgs[i] != nullptr) {
355 if (parameters[i].bOut) {
356 if (parameters[i].bIn) {
357 uno_destructData(arguments[i], ptds[i], nullptr);
358 }
360 arguments[i], cppArgs[i], ptds[i],
361 proxy->getBridge()->getCpp2Uno());
362 }
364 cppArgs[i], ptds[i],
365 reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release));
366 TYPELIB_DANGER_RELEASE(ptds[i]);
367 }
368 }
369 switch (retKind) {
371 switch (rtd->eTypeClass) {
372 case typelib_TypeClass_VOID:
373 break;
374 case typelib_TypeClass_BOOLEAN:
375 case typelib_TypeClass_BYTE:
376 case typelib_TypeClass_SHORT:
377 case typelib_TypeClass_UNSIGNED_SHORT:
378 case typelib_TypeClass_LONG:
379 case typelib_TypeClass_UNSIGNED_LONG:
380 case typelib_TypeClass_HYPER:
381 case typelib_TypeClass_UNSIGNED_HYPER:
382 case typelib_TypeClass_CHAR:
383 case typelib_TypeClass_ENUM:
384 case typelib_TypeClass_STRUCT:
385 std::memcpy(ret, gpr, rtd->nSize);
386 break;
387 case typelib_TypeClass_FLOAT:
388 case typelib_TypeClass_DOUBLE:
389 std::memcpy(ret, fpr, rtd->nSize);
390 break;
391 default:
392 assert(false);
393 }
394 break;
396 switch (rtd->nSize) {
397 case 16:
398 std::memcpy(static_cast<char *>(ret) + 12, fpr + 3, 4);
399 [[fallthrough]];
400 case 12:
401 std::memcpy(static_cast<char *>(ret) + 8, fpr + 2, 4);
402 [[fallthrough]];
403 case 8:
404 std::memcpy(static_cast<char *>(ret) + 4, fpr + 1, 4);
405 [[fallthrough]];
406 case 4:
407 std::memcpy(ret, fpr, 4);
408 break;
409 default:
410 assert(false);
411 }
412 break;
414 std::memcpy(ret, fpr, rtd->nSize);
415 break;
417 break;
418 }
419 if (retConv) {
421 returnValue, ret, rtd, proxy->getBridge()->getCpp2Uno());
423 ret, rtd, reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release));
424 }
425 TYPELIB_DANGER_RELEASE(rtd);
426}
427
428}
429
430namespace bridges::cpp_uno::shared {
431
433 uno_Interface * pUnoI, typelib_TypeDescription const * pMemberDescr,
434 void * pReturn, void ** pArgs, uno_Any ** ppException)
435{
436 UnoInterfaceProxy * proxy = static_cast<UnoInterfaceProxy *>(pUnoI);
437 switch (pMemberDescr->eTypeClass) {
438 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
439 {
440 typelib_InterfaceAttributeTypeDescription const * atd
441 = reinterpret_cast<
442 typelib_InterfaceAttributeTypeDescription const *>(
443 pMemberDescr);
444 VtableSlot slot(getVtableSlot(atd));
445 if (pReturn != nullptr) { // getter
446 call(
447 proxy, slot, atd->pAttributeTypeRef, 0, nullptr, pReturn, pArgs,
448 ppException);
449 } else { // setter
450 typelib_MethodParameter param = {
451 nullptr, atd->pAttributeTypeRef, true, false };
452 typelib_TypeDescriptionReference * rtd = nullptr;
454 &rtd, typelib_TypeClass_VOID, OUString("void").pData);
455 slot.index += 1;
456 call(proxy, slot, rtd, 1, &param, pReturn, pArgs, ppException);
458 }
459 break;
460 }
461 case typelib_TypeClass_INTERFACE_METHOD:
462 {
463 typelib_InterfaceMethodTypeDescription const * mtd
464 = reinterpret_cast<
465 typelib_InterfaceMethodTypeDescription const *>(
466 pMemberDescr);
467 VtableSlot slot(getVtableSlot(mtd));
468 switch (slot.index) {
469 case 1:
470 pUnoI->acquire(pUnoI);
471 *ppException = nullptr;
472 break;
473 case 2:
474 pUnoI->release(pUnoI);
475 *ppException = nullptr;
476 break;
477 case 0:
478 {
479 typelib_TypeDescription * td = nullptr;
480 TYPELIB_DANGER_GET(
481 &td,
482 (static_cast<css::uno::Type *>(pArgs[0])
483 ->getTypeLibType()));
484 if (td != nullptr) {
485 uno_Interface * ifc = nullptr;
486 proxy->pBridge->getUnoEnv()->getRegisteredInterface(
487 proxy->pBridge->getUnoEnv(),
488 reinterpret_cast<void **>(&ifc), proxy->oid.pData,
489 reinterpret_cast<
490 typelib_InterfaceTypeDescription *>(td));
491 if (ifc != nullptr) {
493 static_cast<uno_Any *>(pReturn), &ifc, td,
494 nullptr);
495 ifc->release(ifc);
496 TYPELIB_DANGER_RELEASE(td);
497 *ppException = nullptr;
498 break;
499 }
500 TYPELIB_DANGER_RELEASE(td);
501 }
502 }
503 [[fallthrough]];
504 default:
505 call(
506 proxy, slot, mtd->pReturnTypeRef, mtd->nParams,
507 mtd->pParams, pReturn, pArgs, ppException);
508 break;
509 }
510 break;
511 }
512 default:
513 assert(false);
514 }
515}
516
517}
518
519/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr sal_Int8 header[]
void SAL_CALL uno_any_construct(uno_Any *pDest, void *pSource, typelib_TypeDescription *pTypeDescr, uno_AcquireFunc acquire) SAL_THROW_EXTERN_C()
void callVirtualFunction(unsigned long function, unsigned long *gpr, unsigned long *fpr, unsigned long *stack, sal_Int32 sp, void *ret)
uno_Mapping * getUno2Cpp()
Definition: bridge.hxx:73
uno_ExtEnvironment * getUnoEnv()
Definition: bridge.hxx:70
uno_Mapping * getCpp2Uno()
Definition: bridge.hxx:72
A uno proxy wrapping a cpp interface.
com::sun::star::uno::XInterface * getCppI()
Any value
void SAL_CALL uno_destructData(void *pValue, typelib_TypeDescription *pTypeDescr, uno_ReleaseFunc release) SAL_THROW_EXTERN_C()
void SAL_CALL uno_constructData(void *pMem, typelib_TypeDescription *pTypeDescr) SAL_THROW_EXTERN_C()
void SAL_CALL uno_copyAndConvertData(void *pDest, void *pSource, typelib_TypeDescription *pTypeDescr, uno_Mapping *mapping) SAL_THROW_EXTERN_C()
char const * name
std::unique_ptr< sal_Int32[]> pData
struct _typelib_TypeDescription typelib_TypeDescription
Definition: msvc/except.hxx:52
struct _uno_Any uno_Any
Definition: msvc/except.hxx:31
__cxa_eh_globals * __cxa_get_globals()
std::type_info * __cxa_current_exception_type()
ReturnKind getReturnKind(typelib_TypeDescription const *type)
void mapException(__cxxabiv1::__cxa_exception *exception, std::type_info const *type, uno_Any *any, uno_Mapping *mapping)
void unoInterfaceProxyDispatch(uno_Interface *pUnoI, const typelib_TypeDescription *pMemberDescr, void *pReturn, void *pArgs[], uno_Any **ppException)
VtableSlot getVtableSlot(typelib_InterfaceAttributeTypeDescription const *ifcMember)
Calculates the vtable slot associated with an interface attribute member.
Definition: vtables.cxx:132
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
int i
Represents a vtable slot of a C++ class.
Definition: vtables.hxx:60
sal_Int32 index
The index within the vtable.
Definition: vtables.hxx:76
sal_Int32 offset
The offset of the vtable.
Definition: vtables.hxx:68
void SAL_CALL typelib_typedescriptionreference_new(typelib_TypeDescriptionReference **ppTDR, typelib_TypeClass eTypeClass, rtl_uString *pTypeName) SAL_THROW_EXTERN_C()
void SAL_CALL typelib_typedescriptionreference_release(typelib_TypeDescriptionReference *pRef) SAL_THROW_EXTERN_C()
unsigned char sal_Bool
sal_uInt16 sal_Unicode
signed char sal_Int8