tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / bridges / source / cpp_uno / gcc3_linux_riscv64 / cpp2uno.cxx
blob731eb12cf96d6b567fb8293fc1d42235ff2a497f
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.
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 .
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"
32 #include <cstring>
33 #include <typeinfo>
35 using namespace com::sun::star::uno;
37 namespace CPPU_CURRENT_NAMESPACE
39 bool is_complex_struct(const typelib_TypeDescription* type)
41 const typelib_CompoundTypeDescription* p
42 = reinterpret_cast<const typelib_CompoundTypeDescription*>(type);
43 for (sal_Int32 i = 0; i < p->nMembers; ++i)
45 if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT
46 || p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION)
48 typelib_TypeDescription* t = 0;
49 TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]);
50 bool b = is_complex_struct(t);
51 TYPELIB_DANGER_RELEASE(t);
52 if (b)
54 return true;
57 else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass))
58 return true;
60 if (p->pBaseTypeDescription != 0)
61 return is_complex_struct(&p->pBaseTypeDescription->aBase);
62 return false;
65 bool return_in_hidden_param(typelib_TypeDescriptionReference* pTypeRef)
67 if (bridges::cpp_uno::shared::isSimpleType(pTypeRef))
68 return false;
69 else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT
70 || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
72 typelib_TypeDescription* pTypeDescr = 0;
73 TYPELIB_DANGER_GET(&pTypeDescr, pTypeRef);
75 //A Composite Type not larger than 16 bytes is returned in up to two GPRs
76 bool bRet = pTypeDescr->nSize > 16 || is_complex_struct(pTypeDescr);
78 TYPELIB_DANGER_RELEASE(pTypeDescr);
79 return bRet;
81 return true;
85 namespace
87 static sal_Int32
88 cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy* pThis,
89 const typelib_TypeDescription* pMemberTypeDescr,
90 typelib_TypeDescriptionReference* pReturnTypeRef, // 0 indicates void return
91 sal_Int32 nParams, typelib_MethodParameter* pParams, void** gpreg, void** fpreg,
92 void** ovrflw, sal_uInt64* pRegisterReturn /* space for register return */)
94 BRIDGE_LOG("In cpp2uno_call, pThis = %p, pMemberTypeDescr = %p, pReturnTypeRef = %p\n", pThis,
95 pMemberTypeDescr, pReturnTypeRef);
96 BRIDGE_LOG("In cpp2uno_call, nParams = %d, pParams = %p, pRegisterReturn = %p\n", nParams,
97 pParams, pRegisterReturn);
98 BRIDGE_LOG("In cpp2uno_call, gpreg = %p, fpreg = %p, ovrflw = %p\n", gpreg, fpreg, ovrflw);
100 unsigned int nr_gpr = 0;
101 unsigned int nr_fpr = 0;
103 BRIDGE_LOG("cpp2uno_call:begin\n");
105 // return
106 typelib_TypeDescription* pReturnTypeDescr = 0;
107 if (pReturnTypeRef)
108 TYPELIB_DANGER_GET(&pReturnTypeDescr, pReturnTypeRef);
110 void* pUnoReturn = 0;
111 void* pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
113 if (pReturnTypeDescr)
115 if (CPPU_CURRENT_NAMESPACE::return_in_hidden_param(pReturnTypeRef))
117 pCppReturn = *gpreg++; // complex return via ptr (pCppReturn)
118 nr_gpr++;
120 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr)
121 ? alloca(pReturnTypeDescr->nSize)
122 : pCppReturn); // direct way
123 BRIDGE_LOG("cpp2uno_call:complexreturn\n");
125 else
127 pUnoReturn = pRegisterReturn; // direct way for simple types
128 BRIDGE_LOG("cpp2uno_call:simplereturn\n");
132 // pop this
133 // TODO: Is it really essential to pop?
134 gpreg++;
135 nr_gpr++;
137 // stack space
138 static_assert(sizeof(void*) == sizeof(sal_Int64), "### unexpected size!");
139 // parameters
140 void** pUnoArgs = (void**)alloca(4 * sizeof(void*) * nParams);
141 void** pCppArgs = pUnoArgs + nParams;
142 // indices of values this have to be converted (interface conversion cpp<=>uno)
143 sal_Int32* pTempIndices = (sal_Int32*)(pUnoArgs + (2 * nParams));
144 // type descriptions for reconversions
145 typelib_TypeDescription** ppTempParamTypeDescr
146 = (typelib_TypeDescription**)(pUnoArgs + (3 * nParams));
148 sal_Int32 nTempIndices = 0;
150 BRIDGE_LOG("cpp2uno_call:nParams=%d\n", nParams);
152 for (sal_Int32 nPos = 0; nPos < nParams; ++nPos)
154 const typelib_MethodParameter& rParam = pParams[nPos];
156 typelib_TypeDescription* pParamTypeDescr = 0;
157 TYPELIB_DANGER_GET(&pParamTypeDescr, rParam.pTypeRef);
159 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType(pParamTypeDescr)) // value
161 BRIDGE_LOG("cpp2uno_call:Param %u, type %u\n", nPos, pParamTypeDescr->eTypeClass);
162 switch (pParamTypeDescr->eTypeClass)
164 case typelib_TypeClass_FLOAT:
165 case typelib_TypeClass_DOUBLE:
166 if (nr_fpr < MAX_FP_REGS)
168 BRIDGE_LOG("cpp2uno_call:fpr=%p\n", *fpreg);
169 pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++;
170 nr_fpr++;
172 else if (nr_gpr < MAX_GP_REGS)
174 BRIDGE_LOG("cpp2uno_call:fpr=%p\n", *gpreg);
175 pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++;
176 nr_gpr++;
178 else
180 BRIDGE_LOG("cpp2uno_call:fpr=%p\n", *ovrflw);
181 pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
184 break;
186 default:
187 if (nr_gpr < MAX_GP_REGS)
189 BRIDGE_LOG("cpp2uno_call:gpr=%p\n", *gpreg);
190 pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++;
191 nr_gpr++;
193 else
195 BRIDGE_LOG("cpp2uno_call:gpr=%p\n", *ovrflw);
196 pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
198 break;
200 // no longer needed
201 TYPELIB_DANGER_RELEASE(pParamTypeDescr);
203 else // ptr to complex value | ref
205 BRIDGE_LOG("cpp2uno_call:ptr|ref\n");
206 void* pCppStack;
207 if (nr_gpr < MAX_GP_REGS)
209 pCppArgs[nPos] = pCppStack = *gpreg++;
210 nr_gpr++;
212 else
214 pCppArgs[nPos] = pCppStack = *ovrflw++;
216 BRIDGE_LOG("cpp2uno_call:pCppStack=%p\n", pCppStack);
218 if (!rParam.bIn) // is pure out
220 // uno out is unconstructed mem!
221 pUnoArgs[nPos] = alloca(pParamTypeDescr->nSize);
222 pTempIndices[nTempIndices] = nPos;
223 // will be released at reconversion
224 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
226 // is in/inout
227 else if (bridges::cpp_uno::shared::relatesToInterfaceType(pParamTypeDescr))
229 uno_copyAndConvertData(pUnoArgs[nPos] = alloca(pParamTypeDescr->nSize), pCppStack,
230 pParamTypeDescr, pThis->getBridge()->getCpp2Uno());
231 pTempIndices[nTempIndices] = nPos; // has to be reconverted
232 // will be released at reconversion
233 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
234 BRIDGE_LOG("cpp2uno_call:related to interface,%p,%d,pUnoargs[%d]=%p\n", pCppStack,
235 pParamTypeDescr->nSize, nPos, pUnoArgs[nPos]);
237 else // direct way
239 pUnoArgs[nPos] = pCppStack;
240 BRIDGE_LOG("cpp2uno_call:direct,pUnoArgs[%d]=%p\n", nPos, pUnoArgs[nPos]);
241 // no longer needed
242 TYPELIB_DANGER_RELEASE(pParamTypeDescr);
246 BRIDGE_LOG("cpp2uno_call2,%p,unoargs=%p\n", pThis->getUnoI()->pDispatcher, pUnoArgs);
247 BRIDGE_LOG("pMemberTypeDescr=%p,pUnoReturn=%p\n", pMemberTypeDescr, pUnoReturn);
249 // ExceptionHolder
250 uno_Any aUnoExc; // Any will be constructed by callee
251 uno_Any* pUnoExc = &aUnoExc;
252 BRIDGE_LOG("pThis=%p,pThis->getUnoI()=%p,pMemberTypeDescr=%p\npUnoReturn=%p,pUnoArgs=%p", pThis,
253 pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs);
254 // invoke uno dispatch call
255 (*pThis->getUnoI()->pDispatcher)(pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs,
256 &pUnoExc);
257 BRIDGE_LOG("cpp2uno_call2,after dispatch\n");
259 // in case an exception occurred...
260 if (pUnoExc)
262 // destruct temporary in/inout params
263 for (; nTempIndices--;)
265 sal_Int32 nIndex = pTempIndices[nTempIndices];
267 if (pParams[nIndex].bIn) // is in/inout => was constructed
268 uno_destructData(pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndices], 0);
269 TYPELIB_DANGER_RELEASE(ppTempParamTypeDescr[nTempIndices]);
271 if (pReturnTypeDescr)
272 TYPELIB_DANGER_RELEASE(pReturnTypeDescr);
274 CPPU_CURRENT_NAMESPACE::raiseException(&aUnoExc, pThis->getBridge()->getUno2Cpp());
275 // has to destruct the any
276 // is here for dummy
277 return typelib_TypeClass_VOID;
279 else // else no exception occurred...
281 // temporary params
282 for (; nTempIndices--;)
284 sal_Int32 nIndex = pTempIndices[nTempIndices];
285 typelib_TypeDescription* pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
287 if (pParams[nIndex].bOut) // inout/out
289 // convert and assign
290 uno_destructData(pCppArgs[nIndex], pParamTypeDescr, cpp_release);
291 uno_copyAndConvertData(pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
292 pThis->getBridge()->getUno2Cpp());
294 // destroy temp uno param
295 uno_destructData(pUnoArgs[nIndex], pParamTypeDescr, 0);
297 TYPELIB_DANGER_RELEASE(pParamTypeDescr);
299 //void* retout = nullptr; // avoid false -Werror=maybe-uninitialized
300 // return
301 sal_Int32 returnType = 0;
302 if (pReturnTypeDescr)
304 if (!bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr))
306 const bool isSigned = true;
307 switch (pReturnTypeDescr == nullptr ? typelib_TypeClass_VOID
308 : pReturnTypeDescr->eTypeClass)
310 // Sometimes we need to return a smaller type into a larger type.
312 // For example, in pyuno.cxx:PyUNO_bool(), an int(32bit) is returned
313 // in type Py_ssize_t(64bit)
314 // We assume that this 32bit int was put in low 32 bit of register a0.
315 // The bridge may return with high 32 bit uncleaned and compiler might
316 // directly bind this register to 64 bit variable.
318 // This bug occurs when build pyuno with gcc-12 with -O2.
319 // https://bugs.documentfoundation.org/show_bug.cgi?id=155937
321 // So we need to clean the higher bits in bridge.
322 case typelib_TypeClass_BOOLEAN:
323 abi_riscv64::extIntBits(pRegisterReturn,
324 reinterpret_cast<sal_uInt64*>(pUnoReturn),
325 !isSigned, 1);
326 break;
327 case typelib_TypeClass_BYTE:
328 abi_riscv64::extIntBits(pRegisterReturn,
329 reinterpret_cast<sal_uInt64*>(pUnoReturn), isSigned,
331 break;
332 case typelib_TypeClass_CHAR:
333 case typelib_TypeClass_UNSIGNED_SHORT:
334 abi_riscv64::extIntBits(pRegisterReturn,
335 reinterpret_cast<sal_uInt64*>(pUnoReturn),
336 !isSigned, 2);
337 break;
338 case typelib_TypeClass_SHORT:
339 abi_riscv64::extIntBits(pRegisterReturn,
340 reinterpret_cast<sal_uInt64*>(pUnoReturn), isSigned,
342 break;
343 case typelib_TypeClass_UNSIGNED_LONG:
344 abi_riscv64::extIntBits(pRegisterReturn,
345 reinterpret_cast<sal_uInt64*>(pUnoReturn),
346 !isSigned, 4);
347 break;
348 case typelib_TypeClass_LONG:
349 abi_riscv64::extIntBits(pRegisterReturn,
350 reinterpret_cast<sal_uInt64*>(pUnoReturn), isSigned,
352 break;
353 // TODO: check the source of the enum type.
354 case typelib_TypeClass_ENUM:
355 case typelib_TypeClass_UNSIGNED_HYPER:
356 case typelib_TypeClass_HYPER:
357 std::memcpy(reinterpret_cast<char*>(pRegisterReturn), pUnoReturn, 8);
358 break;
359 case typelib_TypeClass_FLOAT:
360 std::memcpy(reinterpret_cast<char*>(pRegisterReturn), pUnoReturn, 4);
361 std::memset(reinterpret_cast<char*>(pRegisterReturn) + 4, 0xFF, 4);
362 break;
363 case typelib_TypeClass_DOUBLE:
364 std::memcpy(reinterpret_cast<char*>(pRegisterReturn), pUnoReturn, 8);
365 break;
366 case typelib_TypeClass_STRUCT:
367 case typelib_TypeClass_EXCEPTION:
368 abi_riscv64::splitUNOStruct(
369 pReturnTypeDescr, reinterpret_cast<sal_uInt64*>(pRegisterReturn),
370 reinterpret_cast<sal_uInt64*>(pUnoReturn), returnType);
371 break;
372 case typelib_TypeClass_VOID:
373 break;
374 default:
375 if (pUnoReturn)
377 std::memcpy(pRegisterReturn, pUnoReturn, 16);
379 BRIDGE_LOG("Unhandled Type: %d\n", pReturnTypeDescr->eTypeClass);
382 else
384 uno_copyAndConvertData(pCppReturn, pUnoReturn, pReturnTypeDescr,
385 pThis->getBridge()->getUno2Cpp());
386 // destroy temp uno return
387 uno_destructData(pUnoReturn, pReturnTypeDescr, 0);
388 // complex return ptr is set to return reg
389 *(void**)pRegisterReturn = pCppReturn;
391 TYPELIB_DANGER_RELEASE(pReturnTypeDescr);
393 return returnType;
398 * is called on incoming vtable calls
399 * (called by asm snippets)
401 sal_Int32 cpp_vtable_call(sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, void** gpreg,
402 void** fpreg, void** ovrflw,
403 sal_uInt64* pRegisterReturn /* space for register return */)
405 static_assert(sizeof(sal_Int64) == sizeof(void*), "### unexpected!");
407 BRIDGE_LOG("in cpp_vtable_call nFunctionIndex is %d\n", nFunctionIndex);
408 BRIDGE_LOG("in cpp_vtable_call nVtableOffset is %d\n", nVtableOffset);
409 BRIDGE_LOG("in cpp_vtable_call gp=%p, fp=%p, ov=%p\n", gpreg, fpreg, ovrflw);
411 // gpreg: [ret *], this, [other gpr params]
412 // fpreg: [fpr params]
413 // ovrflw: [gpr or fpr params (properly aligned)]
414 void* pThis;
415 if (nFunctionIndex & 0x80000000)
417 nFunctionIndex &= 0x7fffffff;
418 pThis = gpreg[1];
420 else
422 pThis = gpreg[0];
424 BRIDGE_LOG("cpp_vtable_call, pThis=%p, nFunctionIndex=%d, nVtableOffset=%d\n", pThis,
425 nFunctionIndex, nVtableOffset);
427 pThis = static_cast<char*>(pThis) - nVtableOffset;
428 bridges::cpp_uno::shared::CppInterfaceProxy* pCppI
429 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(pThis);
430 BRIDGE_LOG("cpp_vtable_call, pCppI=%p\n", pCppI);
432 typelib_InterfaceTypeDescription* pTypeDescr = pCppI->getTypeDescr();
434 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
436 SAL_WARN("bridges", "illegal " << OUString::unacquired(&pTypeDescr->aBase.pTypeName)
437 << " vtable index " << nFunctionIndex << "/"
438 << pTypeDescr->nMapFunctionIndexToMemberIndex);
439 throw RuntimeException(("illegal " + OUString::unacquired(&pTypeDescr->aBase.pTypeName)
440 + " vtable index " + OUString::number(nFunctionIndex) + "/"
441 + OUString::number(pTypeDescr->nMapFunctionIndexToMemberIndex)),
442 (XInterface*)pThis);
445 // determine called method
446 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
447 assert(nMemberPos < pTypeDescr->nAllMembers);
449 TypeDescription aMemberDescr(pTypeDescr->ppAllMembers[nMemberPos]);
451 sal_Int32 eRet;
452 switch (aMemberDescr.get()->eTypeClass)
454 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
456 BRIDGE_LOG("cpp_vtable_call interface attribute\n");
457 typelib_TypeDescriptionReference* pAttrTypeRef
458 = reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(aMemberDescr.get())
459 ->pAttributeTypeRef;
461 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
463 // is GET method
464 eRet = cpp2uno_call(pCppI, aMemberDescr.get(), pAttrTypeRef, 0, 0, // no params
465 gpreg, fpreg, ovrflw, pRegisterReturn);
467 else
469 // is SET method
470 typelib_MethodParameter aParam;
471 aParam.pTypeRef = pAttrTypeRef;
472 aParam.bIn = sal_True;
473 aParam.bOut = sal_False;
475 eRet = cpp2uno_call(pCppI, aMemberDescr.get(),
476 0, // indicates void return
477 1, &aParam, gpreg, fpreg, ovrflw, pRegisterReturn);
479 break;
481 case typelib_TypeClass_INTERFACE_METHOD:
483 BRIDGE_LOG("cpp_vtable_call interface method\n");
484 // is METHOD
485 switch (nFunctionIndex)
487 case 1: // acquire()
488 BRIDGE_LOG("cpp_vtable_call method acquire\n");
489 pCppI->acquireProxy(); // non virtual call!
490 eRet = 0;
491 break;
492 case 2: // release()
493 BRIDGE_LOG("cpp_vtable_call method release\n");
494 pCppI->releaseProxy(); // non virtual call!
495 eRet = 0;
496 break;
497 case 0: // queryInterface() opt
499 BRIDGE_LOG("cpp_vtable_call method query interface opt\n");
500 typelib_TypeDescription* pTD = 0;
501 TYPELIB_DANGER_GET(&pTD, reinterpret_cast<Type*>(gpreg[2])->getTypeLibType());
502 if (pTD)
504 XInterface* pInterface = 0;
505 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
506 pCppI->getBridge()->getCppEnv(), (void**)&pInterface,
507 pCppI->getOid().pData,
508 reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD));
510 if (pInterface)
512 ::uno_any_construct(reinterpret_cast<uno_Any*>(gpreg[0]), &pInterface,
513 pTD, cpp_acquire);
515 pInterface->release();
516 TYPELIB_DANGER_RELEASE(pTD);
518 reinterpret_cast<void**>(pRegisterReturn)[0] = gpreg[0];
519 eRet = 0;
520 break;
522 TYPELIB_DANGER_RELEASE(pTD);
524 [[fallthrough]];
525 } // else perform queryInterface()
526 default:
527 BRIDGE_LOG("cpp_vtable_call method query interface\n");
528 typelib_InterfaceMethodTypeDescription* pMethodTD
529 = reinterpret_cast<typelib_InterfaceMethodTypeDescription*>(
530 aMemberDescr.get());
532 eRet = cpp2uno_call(pCppI, aMemberDescr.get(), pMethodTD->pReturnTypeRef,
533 pMethodTD->nParams, pMethodTD->pParams, gpreg, fpreg,
534 ovrflw, pRegisterReturn);
536 break;
538 default:
540 BRIDGE_LOG("cpp_vtable_call no member\n");
541 throw RuntimeException("no member description found!", (XInterface*)pThis);
545 return eRet;
548 extern "C" void privateSnippetExecutor(...);
550 int const codeSnippetSize = 0x6c;
552 unsigned char* codeSnippet(unsigned char* code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
553 bool bHasHiddenParam)
555 BRIDGE_LOG("in codeSnippet functionIndex is %d\n", functionIndex);
556 BRIDGE_LOG("in codeSnippet vtableOffset is %d\n", vtableOffset);
557 BRIDGE_LOG("in codeSnippet privateSnippetExecutor is %lx\n",
558 (unsigned long)privateSnippetExecutor);
559 BRIDGE_LOG("in codeSnippet cpp_vtable_call is %lx\n", (unsigned long)cpp_vtable_call);
561 if (bHasHiddenParam)
562 functionIndex |= 0x80000000;
564 unsigned int* p = (unsigned int*)code;
566 assert((((unsigned long)code) & 0x3) == 0); //aligned to 4 otherwise a mistake
568 /* generate this code */
570 It is complex to load a 64bit address because you cannot load
571 an unsigned number to register on RISC-V.
572 # load functionIndex to t4
573 00000eb7 lui t4,0x0
574 000eee93 ori t4,t4,0x0
575 # load privateSnippetExecutor to t0
576 000002b7 lui t0,0x0
577 02429293 slli t0,t0,36
578 00000337 lui t1,0x0
579 01431313 slli t1,t1,20
580 0062e2b3 or t0,t0,t1
581 00000337 lui t1,0x0
582 00431313 slli t1,t1,4
583 0062e2b3 or t0,t0,t1
584 00000337 lui t1,0x0
585 00c35313 srli t1,t1,12
586 0062e2b3 or t0,t0,t1
587 # load cpp_vtable_call to t6
588 00000fb7 lui t6,0x0
589 024f9f93 slli t6,t6,36
590 00000337 lui t1,0x0
591 01431313 slli t1,t1,20
592 006fefb3 or t6,t6,t1
593 00000337 lui t1,0x0
594 00431313 slli t1,t1,4
595 006fefb3 or t6,t6,t1
596 00000337 lui t1,0x0
597 00c35313 srli t1,t1,12
598 006fefb3 or t6,t6,t1
599 # load vtableOffset to t5
600 00000f37 lui t5,0x0
601 000f6f13 ori t5,t5,0x0
602 # jump to privateSnippetExecutor
603 00028067 jalr zero,t0,0x0
606 *p++ = 0x00000eb7 | ((functionIndex)&0xfffff000);
607 *p++ = 0x000eee93 | ((functionIndex << 20) & 0xfff00000);
609 // load privateSnippetExecutor to t0
610 unsigned long functionEntry = ((unsigned long)privateSnippetExecutor);
611 *p++ = 0x000002b7 | ((functionEntry >> 36) & 0x000000000ffff000);
612 *p++ = 0x02429293;
613 *p++ = 0x00000337 | ((functionEntry >> 20) & 0x000000000ffff000);
614 *p++ = 0x01431313;
615 *p++ = 0x0062e2b3;
616 *p++ = 0x00000337 | ((functionEntry >> 4) & 0x000000000ffff000);
617 *p++ = 0x00431313;
618 *p++ = 0x0062e2b3;
619 *p++ = 0x00000337 | ((functionEntry << 12) & 0x000000000ffff000);
620 *p++ = 0x00c35313;
621 *p++ = 0x0062e2b3;
622 // load cpp_vtable_call to t6
623 functionEntry = (unsigned long)cpp_vtable_call;
624 *p++ = 0x00000fb7 | ((functionEntry >> 36) & 0x000000000ffff000);
625 *p++ = 0x024f9f93;
626 *p++ = 0x00000337 | ((functionEntry >> 20) & 0x000000000ffff000);
627 *p++ = 0x01431313;
628 *p++ = 0x006fefb3;
629 *p++ = 0x00000337 | ((functionEntry >> 4) & 0x000000000ffff000);
630 *p++ = 0x00431313;
631 *p++ = 0x006fefb3;
632 *p++ = 0x00000337 | ((functionEntry << 12) & 0x000000000ffff000);
633 *p++ = 0x00c35313;
634 *p++ = 0x006fefb3;
635 // load vtableOffset to t5
636 *p++ = 0x00000f37 | ((vtableOffset)&0xfffff000);
637 *p++ = 0x000f6f13 | ((vtableOffset << 20) & 0xfff00000);
638 // jump to privateSnippetExecutor
639 *p++ = 0x00028067;
640 return (code + codeSnippetSize);
644 void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const*, unsigned char const*)
646 asm volatile("fence" :::);
649 struct bridges::cpp_uno::shared::VtableFactory::Slot
651 void const* fn;
654 bridges::cpp_uno::shared::VtableFactory::Slot*
655 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void* block)
657 return static_cast<Slot*>(block) + 2;
660 std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize(sal_Int32 slotCount)
662 return (slotCount + 2) * sizeof(Slot) + slotCount * codeSnippetSize;
665 namespace
667 // Some dummy type whose RTTI is used in the synthesized proxy vtables to make uses of dynamic_cast
668 // on such proxy objects not crash:
669 struct ProxyRtti
674 bridges::cpp_uno::shared::VtableFactory::Slot*
675 bridges::cpp_uno::shared::VtableFactory::initializeBlock(void* block, sal_Int32 slotCount,
676 sal_Int32,
677 typelib_InterfaceTypeDescription*)
679 Slot* slots = mapBlockToVtable(block);
680 slots[-2].fn = 0; //null
681 slots[-1].fn = &typeid(ProxyRtti);
682 return slots + slotCount;
685 unsigned char* bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
686 Slot** slots, unsigned char* code, sal_PtrDiff writetoexecdiff,
687 typelib_InterfaceTypeDescription const* type, sal_Int32 functionOffset, sal_Int32 functionCount,
688 sal_Int32 vtableOffset)
690 (*slots) -= functionCount;
691 Slot* s = *slots;
693 BRIDGE_LOG("in addLocalFunctions functionOffset is %d\n", functionOffset);
694 BRIDGE_LOG("in addLocalFunctions vtableOffset is %d\n", vtableOffset);
695 BRIDGE_LOG("nMembers=%d\n", type->nMembers);
697 for (sal_Int32 i = 0; i < type->nMembers; ++i)
699 typelib_TypeDescription* member = 0;
700 TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
701 assert(member != 0);
702 switch (member->eTypeClass)
704 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
705 // Getter:
706 (s++)->fn = code + writetoexecdiff;
707 code = codeSnippet(
708 code, functionOffset++, vtableOffset,
709 CPPU_CURRENT_NAMESPACE::return_in_hidden_param(
710 reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(member)
711 ->pAttributeTypeRef));
713 // Setter:
714 if (!reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(member)
715 ->bReadOnly)
717 (s++)->fn = code + writetoexecdiff;
718 code = codeSnippet(code, functionOffset++, vtableOffset, false);
720 break;
722 case typelib_TypeClass_INTERFACE_METHOD:
723 (s++)->fn = code + writetoexecdiff;
724 code = codeSnippet(
725 code, functionOffset++, vtableOffset,
726 CPPU_CURRENT_NAMESPACE::return_in_hidden_param(
727 reinterpret_cast<typelib_InterfaceMethodTypeDescription*>(member)
728 ->pReturnTypeRef));
729 break;
731 default:
732 assert(false);
733 break;
735 TYPELIB_DANGER_RELEASE(member);
737 return code;
740 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */