LibreOffice Module bridges (master) 1
gcc3_linux_riscv64/cpp2uno.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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/genfunc.hxx>
20#include <sal/log.hxx>
21#include <typelib/typedescription.hxx>
22#include <uno/data.h>
23#include <osl/endian.h>
24#include "bridge.hxx"
25#include "cppinterfaceproxy.hxx"
26#include "types.hxx"
27#include "vtablefactory.hxx"
28#include "call.hxx"
29#include "share.hxx"
30#include "abi.hxx"
31
32#include <stdio.h>
33//#include <string.h>
34#include <cstring>
35#include <typeinfo>
36
37using namespace com::sun::star::uno;
38
39//#define BRIDGE_DEBUG
40
41#ifdef BRIDGE_DEBUG
42#include <rtl/strbuf.hxx>
43#include <rtl/ustrbuf.hxx>
44using namespace ::std;
45using namespace ::osl;
46using namespace ::rtl;
47#endif
48
50{
52{
53 const typelib_CompoundTypeDescription* p
54 = reinterpret_cast<const typelib_CompoundTypeDescription*>(type);
55 for (sal_Int32 i = 0; i < p->nMembers; ++i)
56 {
57 if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT
58 || p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION)
59 {
61 TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]);
62 bool b = is_complex_struct(t);
63 TYPELIB_DANGER_RELEASE(t);
64 if (b)
65 {
66 return true;
67 }
68 }
69 else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass))
70 return true;
71 }
72 if (p->pBaseTypeDescription != 0)
73 return is_complex_struct(&p->pBaseTypeDescription->aBase);
74 return false;
75}
76
77bool return_in_hidden_param(typelib_TypeDescriptionReference* pTypeRef)
78{
80 return false;
81 else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT
82 || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
83 {
84 typelib_TypeDescription* pTypeDescr = 0;
85 TYPELIB_DANGER_GET(&pTypeDescr, pTypeRef);
86
87 //A Composite Type not larger than 16 bytes is returned in up to two GPRs
88 bool bRet = pTypeDescr->nSize > 16 || is_complex_struct(pTypeDescr);
89
90 TYPELIB_DANGER_RELEASE(pTypeDescr);
91 return bRet;
92 }
93 return true;
94}
95}
96
97namespace
98{
99static sal_Int32
101 const typelib_TypeDescription* pMemberTypeDescr,
102 typelib_TypeDescriptionReference* pReturnTypeRef, // 0 indicates void return
103 sal_Int32 nParams, typelib_MethodParameter* pParams, void** gpreg, void** fpreg,
104 void** ovrflw, sal_uInt64* pRegisterReturn /* space for register return */)
105{
106#ifdef BRIDGE_DEBUG
107 printf("In cpp2uno_call, pThis = %p, pMemberTypeDescr = %p, pReturnTypeRef = %p\n", pThis,
108 pMemberTypeDescr, pReturnTypeRef);
109 printf("In cpp2uno_call, nParams = %d, pParams = %p, pRegisterReturn = %p\n", nParams, pParams,
110 pRegisterReturn);
111 printf("In cpp2uno_call, gpreg = %p, fpreg = %p, ovrflw = %p\n", gpreg, fpreg, ovrflw);
112#endif
113 unsigned int nr_gpr = 0;
114 unsigned int nr_fpr = 0;
115
116 char* gpreg_t = reinterpret_cast<char*>(gpreg);
117 char* fpreg_t = reinterpret_cast<char*>(fpreg);
118
119#ifdef BRIDGE_DEBUG
120 fprintf(stdout, "cpp2uno_call:begin\n");
121#endif
122 // return
123 typelib_TypeDescription* pReturnTypeDescr = 0;
124 if (pReturnTypeRef)
125 TYPELIB_DANGER_GET(&pReturnTypeDescr, pReturnTypeRef);
126
127 void* pUnoReturn = 0;
128 void* pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
129
130 if (pReturnTypeDescr)
131 {
133 {
134 pCppReturn = *gpreg++; // complex return via ptr (pCppReturn)
135 nr_gpr++;
136
137 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr)
138 ? alloca(pReturnTypeDescr->nSize)
139 : pCppReturn); // direct way
140#ifdef BRIDGE_DEBUG
141 fprintf(stdout, "cpp2uno_call:complexreturn\n");
142#endif
143 }
144 else
145 {
146 pUnoReturn = pRegisterReturn; // direct way for simple types
147#ifdef BRIDGE_DEBUG
148 fprintf(stdout, "cpp2uno_call:simplereturn\n");
149#endif
150 }
151 }
152
153 // pop this
154 gpreg++;
155 nr_gpr++;
156
157 // stack space
158 static_assert(sizeof(void*) == sizeof(sal_Int64), "### unexpected size!");
159 // parameters
160 void** pUnoArgs = (void**)alloca(4 * sizeof(void*) * nParams);
161 void** pCppArgs = pUnoArgs + nParams;
162 // indices of values this have to be converted (interface conversion cpp<=>uno)
163 sal_Int32* pTempIndices = (sal_Int32*)(pUnoArgs + (2 * nParams));
164 // type descriptions for reconversions
165 typelib_TypeDescription** ppTempParamTypeDescr
166 = (typelib_TypeDescription**)(pUnoArgs + (3 * nParams));
167
168 sal_Int32 nTempIndices = 0;
169
170#ifdef BRIDGE_DEBUG
171 fprintf(stdout, "cpp2uno_call:nParams=%d\n", nParams);
172#endif
173 for (sal_Int32 nPos = 0; nPos < nParams; ++nPos)
174 {
175 const typelib_MethodParameter& rParam = pParams[nPos];
176
177 typelib_TypeDescription* pParamTypeDescr = 0;
178 TYPELIB_DANGER_GET(&pParamTypeDescr, rParam.pTypeRef);
179
180 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType(pParamTypeDescr)) // value
181 {
182#ifdef BRIDGE_DEBUG
183 fprintf(stdout, "cpp2uno_call:Param %u, type %u\n", nPos, pParamTypeDescr->eTypeClass);
184#endif
185 switch (pParamTypeDescr->eTypeClass)
186 {
187 case typelib_TypeClass_FLOAT:
188 case typelib_TypeClass_DOUBLE:
189 if (nr_fpr < MAX_FP_REGS)
190 {
191#ifdef BRIDGE_DEBUG
192 fprintf(stdout, "cpp2uno_call:fpr=%p\n", *fpreg);
193#endif
194 pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++;
195 nr_fpr++;
196 }
197 else if (nr_gpr < MAX_GP_REGS)
198 {
199#ifdef BRIDGE_DEBUG
200 fprintf(stdout, "cpp2uno_call:fpr=%p\n", *gpreg);
201#endif
202 pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++;
203 nr_gpr++;
204 }
205 else
206 {
207#ifdef BRIDGE_DEBUG
208 fprintf(stdout, "cpp2uno_call:fpr=%p\n", *ovrflw);
209#endif
210 pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
211 }
212
213 break;
214
215 default:
216 if (nr_gpr < MAX_GP_REGS)
217 {
218#ifdef BRIDGE_DEBUG
219 fprintf(stdout, "cpp2uno_call:gpr=%p\n", *gpreg);
220#endif
221 pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++;
222 nr_gpr++;
223 }
224 else
225 {
226#ifdef BRIDGE_DEBUG
227 fprintf(stdout, "cpp2uno_call:gpr=%p\n", *ovrflw);
228#endif
229 pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
230 }
231 break;
232 }
233 // no longer needed
234 TYPELIB_DANGER_RELEASE(pParamTypeDescr);
235 }
236 else // ptr to complex value | ref
237 {
238#ifdef BRIDGE_DEBUG
239 fprintf(stdout, "cpp2uno_call:ptr|ref\n");
240#endif
241 void* pCppStack;
242 if (nr_gpr < MAX_GP_REGS)
243 {
244 pCppArgs[nPos] = pCppStack = *gpreg++;
245 nr_gpr++;
246 }
247 else
248 {
249 pCppArgs[nPos] = pCppStack = *ovrflw++;
250 }
251#ifdef BRIDGE_DEBUG
252 fprintf(stdout, "cpp2uno_call:pCppStack=%p\n", pCppStack);
253#endif
254
255 if (!rParam.bIn) // is pure out
256 {
257 // uno out is unconstructed mem!
258 pUnoArgs[nPos] = alloca(pParamTypeDescr->nSize);
259 pTempIndices[nTempIndices] = nPos;
260 // will be released at reconversion
261 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
262 }
263 // is in/inout
264 else if (bridges::cpp_uno::shared::relatesToInterfaceType(pParamTypeDescr))
265 {
266 uno_copyAndConvertData(pUnoArgs[nPos] = alloca(pParamTypeDescr->nSize), pCppStack,
267 pParamTypeDescr, pThis->getBridge()->getCpp2Uno());
268 pTempIndices[nTempIndices] = nPos; // has to be reconverted
269 // will be released at reconversion
270 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
271#ifdef BRIDGE_DEBUG
272 fprintf(stdout, "cpp2uno_call:related to interface,%p,%d,pUnoargs[%d]=%p\n",
273 pCppStack, pParamTypeDescr->nSize, nPos, pUnoArgs[nPos]);
274#endif
275 }
276 else // direct way
277 {
278 pUnoArgs[nPos] = pCppStack;
279#ifdef BRIDGE_DEBUG
280 fprintf(stdout, "cpp2uno_call:direct,pUnoArgs[%d]=%p\n", nPos, pUnoArgs[nPos]);
281#endif
282 // no longer needed
283 TYPELIB_DANGER_RELEASE(pParamTypeDescr);
284 }
285 }
286 }
287#ifdef BRIDGE_DEBUG
288 fprintf(stdout, "cpp2uno_call2,%p,unoargs=%p\n", pThis->getUnoI()->pDispatcher, pUnoArgs);
289 printf("pMemberTypeDescr=%p,pUnoReturn=%p\n", pMemberTypeDescr, pUnoReturn);
290#endif
291
292 // ExceptionHolder
293 uno_Any aUnoExc; // Any will be constructed by callee
294 uno_Any* pUnoExc = &aUnoExc;
295#ifdef BRIDGE_DEBUG
296 printf("pThis=%p,pThis->getUnoI()=%p,pMemberTypeDescr=%p\npUnoReturn=%p,pUnoArgs=%p", pThis,
297 pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs);
298#endif
299 // invoke uno dispatch call
300 (*pThis->getUnoI()->pDispatcher)(pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs,
301 &pUnoExc);
302#ifdef BRIDGE_DEBUG
303 fprintf(stdout, "cpp2uno_call2,after dispatch\n");
304#endif
305
306 // in case an exception occurred...
307 if (pUnoExc)
308 {
309 fflush(stdout);
310 // destruct temporary in/inout params
311 for (; nTempIndices--;)
312 {
313 sal_Int32 nIndex = pTempIndices[nTempIndices];
314
315 if (pParams[nIndex].bIn) // is in/inout => was constructed
316 uno_destructData(pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndices], 0);
317 TYPELIB_DANGER_RELEASE(ppTempParamTypeDescr[nTempIndices]);
318 }
319 if (pReturnTypeDescr)
320 TYPELIB_DANGER_RELEASE(pReturnTypeDescr);
321
323 // has to destruct the any
324 // is here for dummy
325 return typelib_TypeClass_VOID;
326 }
327 else // else no exception occurred...
328 {
329 // temporary params
330 for (; nTempIndices--;)
331 {
332 sal_Int32 nIndex = pTempIndices[nTempIndices];
333 typelib_TypeDescription* pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
334
335 if (pParams[nIndex].bOut) // inout/out
336 {
337 // convert and assign
338 uno_destructData(pCppArgs[nIndex], pParamTypeDescr, cpp_release);
339 uno_copyAndConvertData(pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
340 pThis->getBridge()->getUno2Cpp());
341 }
342 // destroy temp uno param
343 uno_destructData(pUnoArgs[nIndex], pParamTypeDescr, 0);
344
345 TYPELIB_DANGER_RELEASE(pParamTypeDescr);
346 }
347 void* retout = nullptr; // avoid false -Werror=maybe-uninitialized
348 // return
349 sal_Int32 returnType = 0;
350 if (pReturnTypeDescr)
351 {
352 char* pReturn = reinterpret_cast<char*>(pRegisterReturn);
354 {
355 switch (pReturnTypeDescr == nullptr ? typelib_TypeClass_VOID
356 : pReturnTypeDescr->eTypeClass)
357 {
358 case typelib_TypeClass_HYPER:
359 case typelib_TypeClass_UNSIGNED_HYPER:
360 case typelib_TypeClass_LONG:
361 case typelib_TypeClass_UNSIGNED_LONG:
362 case typelib_TypeClass_ENUM:
363 case typelib_TypeClass_CHAR:
364 case typelib_TypeClass_SHORT:
365 case typelib_TypeClass_UNSIGNED_SHORT:
366 case typelib_TypeClass_BOOLEAN:
367 case typelib_TypeClass_BYTE:
368 std::memcpy(pReturn, pUnoReturn, 8);
369 break;
370 case typelib_TypeClass_FLOAT:
371 std::memcpy(pReturn, pUnoReturn, 4);
372 std::memset(pReturn + 4, 0xFF, 4);
373 break;
374 case typelib_TypeClass_DOUBLE:
375 std::memcpy(pReturn, pUnoReturn, 8);
376 break;
377 case typelib_TypeClass_STRUCT:
378 case typelib_TypeClass_EXCEPTION:
379 {
380 std::memcpy(pReturn, pUnoReturn, 16);
381 sal_Int32 nGreg = 0;
382 sal_Int32 nFreg = 0;
384 nGreg, nFreg,
385 reinterpret_cast<typelib_CompoundTypeDescription const*>(
386 pReturnTypeDescr));
387 if (pReturnTypeDescr->nSize <= 8 && nFreg == 2 && nGreg == 0)
388 {
389 std::memcpy(pReturn + 8, pReturn + 4, 4);
390 std::memset(pReturn + 4, 0xFF, 4);
391 std::memset(pReturn + 12, 0xFF, 4);
392 }
393 else if (nGreg == 1 && nFreg == 1)
394 {
395 returnType = 1;
396 if (pReturnTypeDescr->nSize <= 8)
397 {
398 std::memcpy(pReturn + 8, pReturn + 4, 4);
399 std::memset(pReturn + 12, 0xFF, 4);
400 }
401 }
402 }
403 break;
404 case typelib_TypeClass_VOID:
405 break;
406 default:
407 if (pUnoReturn)
408 {
409 std::memcpy(pRegisterReturn, pUnoReturn, 16);
410 }
411#ifdef BRIDGE_DEBUG
412 printf("Unhandled Type: %d\n", pReturnTypeDescr->eTypeClass);
413#endif
414 }
415 }
416 else
417 {
418 uno_copyAndConvertData(pCppReturn, pUnoReturn, pReturnTypeDescr,
419 pThis->getBridge()->getUno2Cpp());
420 // destroy temp uno return
421 uno_destructData(pUnoReturn, pReturnTypeDescr, 0);
422 // complex return ptr is set to return reg
423 *(void**)pRegisterReturn = pCppReturn;
424 }
425 TYPELIB_DANGER_RELEASE(pReturnTypeDescr);
426 }
427 return returnType;
428 }
429}
430
435sal_Int32 cpp_vtable_call(sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, void** gpreg,
436 void** fpreg, void** ovrflw,
437 sal_uInt64* pRegisterReturn /* space for register return */)
438{
439 static_assert(sizeof(sal_Int64) == sizeof(void*), "### unexpected!");
440
441#ifdef BRIDGE_DEBUG
442 fprintf(stdout, "in cpp_vtable_call nFunctionIndex is %d\n", nFunctionIndex);
443 fprintf(stdout, "in cpp_vtable_call nVtableOffset is %d\n", nVtableOffset);
444 fprintf(stdout, "in cpp_vtable_call gp=%p, fp=%p, ov=%p\n", gpreg, fpreg, ovrflw);
445#endif
446
447 // gpreg: [ret *], this, [other gpr params]
448 // fpreg: [fpr params]
449 // ovrflw: [gpr or fpr params (properly aligned)]
450 void* pThis;
451 if (nFunctionIndex & 0x80000000)
452 {
453 nFunctionIndex &= 0x7fffffff;
454 pThis = gpreg[1];
455 }
456 else
457 {
458 pThis = gpreg[0];
459 }
460#ifdef BRIDGE_DEBUG
461 fprintf(stdout, "cpp_vtable_call, pThis=%p, nFunctionIndex=%d, nVtableOffset=%d\n", pThis,
462 nFunctionIndex, nVtableOffset);
463#endif
464
465 pThis = static_cast<char*>(pThis) - nVtableOffset;
468#ifdef BRIDGE_DEBUG
469 fprintf(stdout, "cpp_vtable_call, pCppI=%p\n", pCppI);
470#endif
471
472 typelib_InterfaceTypeDescription* pTypeDescr = pCppI->getTypeDescr();
473
474 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
475 {
476 SAL_WARN("bridges", "illegal " << OUString::unacquired(&pTypeDescr->aBase.pTypeName)
477 << " vtable index " << nFunctionIndex << "/"
478 << pTypeDescr->nMapFunctionIndexToMemberIndex);
479 throw RuntimeException(("illegal " + OUString::unacquired(&pTypeDescr->aBase.pTypeName)
480 + " vtable index " + OUString::number(nFunctionIndex) + "/"
481 + OUString::number(pTypeDescr->nMapFunctionIndexToMemberIndex)),
482 (XInterface*)pThis);
483 }
484
485 // determine called method
486 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
487 assert(nMemberPos < pTypeDescr->nAllMembers);
488
489 TypeDescription aMemberDescr(pTypeDescr->ppAllMembers[nMemberPos]);
490
491#ifdef BRIDGE_DEBUG
492 //OString cstr( OUStringToOString( aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
493 //fprintf(stdout, "calling %s, nFunctionIndex=%d\n", cstr.getStr(), nFunctionIndex );
494#endif
495 sal_Int32 eRet;
496 switch (aMemberDescr.get()->eTypeClass)
497 {
498 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
499 {
500#ifdef BRIDGE_DEBUG
501 fprintf(stdout, "cpp_vtable_call interface attribute\n");
502#endif
503 typelib_TypeDescriptionReference* pAttrTypeRef
504 = reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(aMemberDescr.get())
505 ->pAttributeTypeRef;
506
507 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
508 {
509 // is GET method
510 eRet = cpp2uno_call(pCppI, aMemberDescr.get(), pAttrTypeRef, 0, 0, // no params
511 gpreg, fpreg, ovrflw, pRegisterReturn);
512 }
513 else
514 {
515 // is SET method
516 typelib_MethodParameter aParam;
517 aParam.pTypeRef = pAttrTypeRef;
518 aParam.bIn = sal_True;
519 aParam.bOut = sal_False;
520
521 eRet = cpp2uno_call(pCppI, aMemberDescr.get(),
522 0, // indicates void return
523 1, &aParam, gpreg, fpreg, ovrflw, pRegisterReturn);
524 }
525 break;
526 }
527 case typelib_TypeClass_INTERFACE_METHOD:
528 {
529#ifdef BRIDGE_DEBUG
530 fprintf(stdout, "cpp_vtable_call interface method\n");
531#endif
532 // is METHOD
533 switch (nFunctionIndex)
534 {
535 case 1: // acquire()
536#ifdef BRIDGE_DEBUG
537 fprintf(stdout, "cpp_vtable_call method acquire\n");
538#endif
539 pCppI->acquireProxy(); // non virtual call!
540 eRet = 0;
541 break;
542 case 2: // release()
543#ifdef BRIDGE_DEBUG
544 fprintf(stdout, "cpp_vtable_call method release\n");
545#endif
546 pCppI->releaseProxy(); // non virtual call!
547 eRet = 0;
548 break;
549 case 0: // queryInterface() opt
550 {
551#ifdef BRIDGE_DEBUG
552 fprintf(stdout, "cpp_vtable_call method query interface opt\n");
553#endif
555 TYPELIB_DANGER_GET(&pTD, reinterpret_cast<Type*>(gpreg[2])->getTypeLibType());
556 if (pTD)
557 {
558 XInterface* pInterface = 0;
559 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
560 pCppI->getBridge()->getCppEnv(), (void**)&pInterface,
561 pCppI->getOid().pData,
562 reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD));
563
564 if (pInterface)
565 {
566 ::uno_any_construct(reinterpret_cast<uno_Any*>(gpreg[0]), &pInterface,
567 pTD, cpp_acquire);
568
569 pInterface->release();
570 TYPELIB_DANGER_RELEASE(pTD);
571
572 reinterpret_cast<void**>(pRegisterReturn)[0] = gpreg[0];
573 eRet = 0;
574 break;
575 }
576 TYPELIB_DANGER_RELEASE(pTD);
577 }
578 } // else perform queryInterface()
579 default:
580#ifdef BRIDGE_DEBUG
581 fprintf(stdout, "cpp_vtable_call method query interface\n");
582#endif
583 typelib_InterfaceMethodTypeDescription* pMethodTD
584 = reinterpret_cast<typelib_InterfaceMethodTypeDescription*>(
585 aMemberDescr.get());
586
587 eRet = cpp2uno_call(pCppI, aMemberDescr.get(), pMethodTD->pReturnTypeRef,
588 pMethodTD->nParams, pMethodTD->pParams, gpreg, fpreg,
589 ovrflw, pRegisterReturn);
590 }
591 break;
592 }
593 default:
594 {
595#ifdef BRIDGE_DEBUG
596 fprintf(stdout, "cpp_vtable_call no member\n");
597#endif
598 throw RuntimeException("no member description found!", (XInterface*)pThis);
599 }
600 }
601
602 return eRet;
603}
604
605extern "C" void privateSnippetExecutor(...);
606
607int const codeSnippetSize = 0x6c;
608
609unsigned char* codeSnippet(unsigned char* code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
610 bool bHasHiddenParam)
611{
612#ifdef BRIDGE_DEBUG
613 fprintf(stdout, "in codeSnippet functionIndex is %d\n", functionIndex);
614 fprintf(stdout, "in codeSnippet vtableOffset is %d\n", vtableOffset);
615 fprintf(stdout, "in codeSnippet privateSnippetExecutor is %lx\n",
616 (unsigned long)privateSnippetExecutor);
617 fprintf(stdout, "in codeSnippet cpp_vtable_call is %lx\n", (unsigned long)cpp_vtable_call);
618
619 fflush(stdout);
620#endif
621
622 if (bHasHiddenParam)
623 functionIndex |= 0x80000000;
624
625 unsigned int* p = (unsigned int*)code;
626
627 assert((((unsigned long)code) & 0x3) == 0); //aligned to 4 otherwise a mistake
628
629 /* generate this code */
630 /*
631 It is complex to load a 64bit address because uou cannot load
632 an unsigned number to register on RISC-V.
633 # load functionIndex to t4
634 00000eb7 lui t4,0x0
635 000eee93 ori t4,t4,0x0
636 # load privateSnippetExecutor to t0
637 000002b7 lui t0,0x0
638 02429293 slli t0,t0,36
639 00000337 lui t1,0x0
640 01431313 slli t1,t1,20
641 0062e2b3 or t0,t0,t1
642 00000337 lui t1,0x0
643 00431313 slli t1,t1,4
644 0062e2b3 or t0,t0,t1
645 00000337 lui t1,0x0
646 00c35313 srli t1,t1,12
647 0062e2b3 or t0,t0,t1
648 # load cpp_vtable_call to t6
649 00000fb7 lui t6,0x0
650 024f9f93 slli t6,t6,36
651 00000337 lui t1,0x0
652 01431313 slli t1,t1,20
653 006fefb3 or t6,t6,t1
654 00000337 lui t1,0x0
655 00431313 slli t1,t1,4
656 006fefb3 or t6,t6,t1
657 00000337 lui t1,0x0
658 00c35313 srli t1,t1,12
659 006fefb3 or t6,t6,t1
660 # load vtableOffset to t5
661 00000f37 lui t5,0x0
662 000f6f13 ori t5,t5,0x0
663 # jump to privateSnippetExecutor
664 00028067 jalr zero,t0,0x0
665 */
666
667 *p++ = 0x00000eb7 | ((functionIndex)&0xfffff000);
668 *p++ = 0x000eee93 | ((functionIndex << 20) & 0xfff00000);
669
670 // load privateSnippetExecutor to t0
671 unsigned long functionEntry = ((unsigned long)privateSnippetExecutor);
672 *p++ = 0x000002b7 | ((functionEntry >> 36) & 0x000000000ffff000);
673 *p++ = 0x02429293;
674 *p++ = 0x00000337 | ((functionEntry >> 20) & 0x000000000ffff000);
675 *p++ = 0x01431313;
676 *p++ = 0x0062e2b3;
677 *p++ = 0x00000337 | ((functionEntry >> 4) & 0x000000000ffff000);
678 *p++ = 0x00431313;
679 *p++ = 0x0062e2b3;
680 *p++ = 0x00000337 | ((functionEntry << 12) & 0x000000000ffff000);
681 *p++ = 0x00c35313;
682 *p++ = 0x0062e2b3;
683 // load cpp_vtable_call to t6
684 functionEntry = (unsigned long)cpp_vtable_call;
685 *p++ = 0x00000fb7 | ((functionEntry >> 36) & 0x000000000ffff000);
686 *p++ = 0x024f9f93;
687 *p++ = 0x00000337 | ((functionEntry >> 20) & 0x000000000ffff000);
688 *p++ = 0x01431313;
689 *p++ = 0x006fefb3;
690 *p++ = 0x00000337 | ((functionEntry >> 4) & 0x000000000ffff000);
691 *p++ = 0x00431313;
692 *p++ = 0x006fefb3;
693 *p++ = 0x00000337 | ((functionEntry << 12) & 0x000000000ffff000);
694 *p++ = 0x00c35313;
695 *p++ = 0x006fefb3;
696 // load vtableOffset to t5
697 *p++ = 0x00000f37 | ((vtableOffset)&0xfffff000);
698 *p++ = 0x000f6f13 | ((vtableOffset << 20) & 0xfff00000);
699 // jump to privateSnippetExecutor
700 *p++ = 0x00028067;
701 return (code + codeSnippetSize);
702}
703}
704
705void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const* bptr,
706 unsigned char const* eptr)
707{
708 asm volatile("fence" :::);
709}
710
712{
713 void const* fn;
714};
715
718{
719 return static_cast<Slot*>(block) + 2;
720}
721
722std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize(sal_Int32 slotCount)
723{
724 return (slotCount + 2) * sizeof(Slot) + slotCount * codeSnippetSize;
725}
726
727namespace
728{
729// Some dummy type whose RTTI is used in the synthesized proxy vtables to make uses of dynamic_cast
730// on such proxy objects not crash:
731struct ProxyRtti
732{
733};
734}
735
737bridges::cpp_uno::shared::VtableFactory::initializeBlock(void* block, sal_Int32 slotCount,
738 sal_Int32,
739 typelib_InterfaceTypeDescription*)
740{
741 Slot* slots = mapBlockToVtable(block);
742 slots[-2].fn = 0; //null
743 slots[-1].fn = &typeid(ProxyRtti);
744 return slots + slotCount;
745}
746
748 Slot** slots, unsigned char* code, sal_PtrDiff writetoexecdiff,
749 typelib_InterfaceTypeDescription const* type, sal_Int32 functionOffset, sal_Int32 functionCount,
750 sal_Int32 vtableOffset)
751{
752 (*slots) -= functionCount;
753 Slot* s = *slots;
754
755#ifdef BRIDGE_DEBUG
756 fprintf(stdout, "in addLocalFunctions functionOffset is %d\n", functionOffset);
757 fprintf(stdout, "in addLocalFunctions vtableOffset is %d\n", vtableOffset);
758 fprintf(stdout, "nMembers=%d\n", type->nMembers);
759 fflush(stdout);
760#endif
761
762 for (sal_Int32 i = 0; i < type->nMembers; ++i)
763 {
764 typelib_TypeDescription* member = 0;
765 TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
766 assert(member != 0);
767 switch (member->eTypeClass)
768 {
769 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
770 // Getter:
771 (s++)->fn = code + writetoexecdiff;
773 code, functionOffset++, vtableOffset,
775 reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(member)
776 ->pAttributeTypeRef));
777
778 // Setter:
779 if (!reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(member)
780 ->bReadOnly)
781 {
782 (s++)->fn = code + writetoexecdiff;
783 code = codeSnippet(code, functionOffset++, vtableOffset, false);
784 }
785 break;
786
787 case typelib_TypeClass_INTERFACE_METHOD:
788 (s++)->fn = code + writetoexecdiff;
790 code, functionOffset++, vtableOffset,
792 reinterpret_cast<typelib_InterfaceMethodTypeDescription*>(member)
793 ->pReturnTypeRef));
794 break;
795
796 default:
797 assert(false);
798 break;
799 }
800 TYPELIB_DANGER_RELEASE(member);
801 }
802 return code;
803}
804
805/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
XPropertyListType t
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()
void cpp_vtable_call(sal_Int32 func, sal_Int32 offset, void **pStack)
is called on incoming vtable calls (called by asm snippets)
void(* privateSnippetExecutor)()
#define MAX_FP_REGS
#define MAX_GP_REGS
const int codeSnippetSize
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
void * p
sal_uInt16 nPos
#define SAL_WARN(area, stream)
struct _typelib_TypeDescription typelib_TypeDescription
Definition: msvc/except.hxx:53
struct _uno_Any uno_Any
Definition: msvc/except.hxx:32
bool return_in_hidden_param(typelib_TypeDescriptionReference *pTypeRef)
void raiseException(uno_Any *pUnoExc, uno_Mapping *pUno2Cpp)
bool is_complex_struct(const typelib_TypeDescription *type)
void countnGreg(sal_Int32 &nGreg, sal_Int32 &nFreg, const typelib_CompoundTypeDescription *pTypeDescr)
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
sal_Unicode code
#define sal_True
#define sal_False
ResultType type