1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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>
23 #include <osl/endian.h>
25 #include "cppinterfaceproxy.hxx"
27 #include "vtablefactory.hxx"
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
);
57 else if (!bridges::cpp_uno::shared::isSimpleType(p
->ppTypeRefs
[i
]->eTypeClass
))
60 if (p
->pBaseTypeDescription
!= 0)
61 return is_complex_struct(&p
->pBaseTypeDescription
->aBase
);
65 bool return_in_hidden_param(typelib_TypeDescriptionReference
* pTypeRef
)
67 if (bridges::cpp_uno::shared::isSimpleType(pTypeRef
))
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
);
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");
106 typelib_TypeDescription
* pReturnTypeDescr
= 0;
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)
120 pUnoReturn
= (bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr
)
121 ? alloca(pReturnTypeDescr
->nSize
)
122 : pCppReturn
); // direct way
123 BRIDGE_LOG("cpp2uno_call:complexreturn\n");
127 pUnoReturn
= pRegisterReturn
; // direct way for simple types
128 BRIDGE_LOG("cpp2uno_call:simplereturn\n");
133 // TODO: Is it really essential to pop?
138 static_assert(sizeof(void*) == sizeof(sal_Int64
), "### unexpected size!");
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
++;
172 else if (nr_gpr
< MAX_GP_REGS
)
174 BRIDGE_LOG("cpp2uno_call:fpr=%p\n", *gpreg
);
175 pCppArgs
[nPos
] = pUnoArgs
[nPos
] = gpreg
++;
180 BRIDGE_LOG("cpp2uno_call:fpr=%p\n", *ovrflw
);
181 pCppArgs
[nPos
] = pUnoArgs
[nPos
] = ovrflw
++;
187 if (nr_gpr
< MAX_GP_REGS
)
189 BRIDGE_LOG("cpp2uno_call:gpr=%p\n", *gpreg
);
190 pCppArgs
[nPos
] = pUnoArgs
[nPos
] = gpreg
++;
195 BRIDGE_LOG("cpp2uno_call:gpr=%p\n", *ovrflw
);
196 pCppArgs
[nPos
] = pUnoArgs
[nPos
] = ovrflw
++;
201 TYPELIB_DANGER_RELEASE(pParamTypeDescr
);
203 else // ptr to complex value | ref
205 BRIDGE_LOG("cpp2uno_call:ptr|ref\n");
207 if (nr_gpr
< MAX_GP_REGS
)
209 pCppArgs
[nPos
] = pCppStack
= *gpreg
++;
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
;
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
]);
239 pUnoArgs
[nPos
] = pCppStack
;
240 BRIDGE_LOG("cpp2uno_call:direct,pUnoArgs[%d]=%p\n", nPos
, pUnoArgs
[nPos
]);
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
);
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
,
257 BRIDGE_LOG("cpp2uno_call2,after dispatch\n");
259 // in case an exception occurred...
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
277 return typelib_TypeClass_VOID
;
279 else // else no exception occurred...
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
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
),
327 case typelib_TypeClass_BYTE
:
328 abi_riscv64::extIntBits(pRegisterReturn
,
329 reinterpret_cast<sal_uInt64
*>(pUnoReturn
), isSigned
,
332 case typelib_TypeClass_CHAR
:
333 case typelib_TypeClass_UNSIGNED_SHORT
:
334 abi_riscv64::extIntBits(pRegisterReturn
,
335 reinterpret_cast<sal_uInt64
*>(pUnoReturn
),
338 case typelib_TypeClass_SHORT
:
339 abi_riscv64::extIntBits(pRegisterReturn
,
340 reinterpret_cast<sal_uInt64
*>(pUnoReturn
), isSigned
,
343 case typelib_TypeClass_UNSIGNED_LONG
:
344 abi_riscv64::extIntBits(pRegisterReturn
,
345 reinterpret_cast<sal_uInt64
*>(pUnoReturn
),
348 case typelib_TypeClass_LONG
:
349 abi_riscv64::extIntBits(pRegisterReturn
,
350 reinterpret_cast<sal_uInt64
*>(pUnoReturn
), isSigned
,
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);
359 case typelib_TypeClass_FLOAT
:
360 std::memcpy(reinterpret_cast<char*>(pRegisterReturn
), pUnoReturn
, 4);
361 std::memset(reinterpret_cast<char*>(pRegisterReturn
) + 4, 0xFF, 4);
363 case typelib_TypeClass_DOUBLE
:
364 std::memcpy(reinterpret_cast<char*>(pRegisterReturn
), pUnoReturn
, 8);
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
);
372 case typelib_TypeClass_VOID
:
377 std::memcpy(pRegisterReturn
, pUnoReturn
, 16);
379 BRIDGE_LOG("Unhandled Type: %d\n", pReturnTypeDescr
->eTypeClass
);
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
);
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)]
415 if (nFunctionIndex
& 0x80000000)
417 nFunctionIndex
&= 0x7fffffff;
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
)),
445 // determine called method
446 sal_Int32 nMemberPos
= pTypeDescr
->pMapFunctionIndexToMemberIndex
[nFunctionIndex
];
447 assert(nMemberPos
< pTypeDescr
->nAllMembers
);
449 TypeDescription
aMemberDescr(pTypeDescr
->ppAllMembers
[nMemberPos
]);
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())
461 if (pTypeDescr
->pMapMemberIndexToFunctionIndex
[nMemberPos
] == nFunctionIndex
)
464 eRet
= cpp2uno_call(pCppI
, aMemberDescr
.get(), pAttrTypeRef
, 0, 0, // no params
465 gpreg
, fpreg
, ovrflw
, pRegisterReturn
);
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
);
481 case typelib_TypeClass_INTERFACE_METHOD
:
483 BRIDGE_LOG("cpp_vtable_call interface method\n");
485 switch (nFunctionIndex
)
488 BRIDGE_LOG("cpp_vtable_call method acquire\n");
489 pCppI
->acquireProxy(); // non virtual call!
493 BRIDGE_LOG("cpp_vtable_call method release\n");
494 pCppI
->releaseProxy(); // non virtual call!
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());
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
));
512 ::uno_any_construct(reinterpret_cast<uno_Any
*>(gpreg
[0]), &pInterface
,
515 pInterface
->release();
516 TYPELIB_DANGER_RELEASE(pTD
);
518 reinterpret_cast<void**>(pRegisterReturn
)[0] = gpreg
[0];
522 TYPELIB_DANGER_RELEASE(pTD
);
525 } // else perform queryInterface()
527 BRIDGE_LOG("cpp_vtable_call method query interface\n");
528 typelib_InterfaceMethodTypeDescription
* pMethodTD
529 = reinterpret_cast<typelib_InterfaceMethodTypeDescription
*>(
532 eRet
= cpp2uno_call(pCppI
, aMemberDescr
.get(), pMethodTD
->pReturnTypeRef
,
533 pMethodTD
->nParams
, pMethodTD
->pParams
, gpreg
, fpreg
,
534 ovrflw
, pRegisterReturn
);
540 BRIDGE_LOG("cpp_vtable_call no member\n");
541 throw RuntimeException("no member description found!", (XInterface
*)pThis
);
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
);
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
574 000eee93 ori t4,t4,0x0
575 # load privateSnippetExecutor to t0
577 02429293 slli t0,t0,36
579 01431313 slli t1,t1,20
582 00431313 slli t1,t1,4
585 00c35313 srli t1,t1,12
587 # load cpp_vtable_call to t6
589 024f9f93 slli t6,t6,36
591 01431313 slli t1,t1,20
594 00431313 slli t1,t1,4
597 00c35313 srli t1,t1,12
599 # load vtableOffset to t5
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);
613 *p
++ = 0x00000337 | ((functionEntry
>> 20) & 0x000000000ffff000);
616 *p
++ = 0x00000337 | ((functionEntry
>> 4) & 0x000000000ffff000);
619 *p
++ = 0x00000337 | ((functionEntry
<< 12) & 0x000000000ffff000);
622 // load cpp_vtable_call to t6
623 functionEntry
= (unsigned long)cpp_vtable_call
;
624 *p
++ = 0x00000fb7 | ((functionEntry
>> 36) & 0x000000000ffff000);
626 *p
++ = 0x00000337 | ((functionEntry
>> 20) & 0x000000000ffff000);
629 *p
++ = 0x00000337 | ((functionEntry
>> 4) & 0x000000000ffff000);
632 *p
++ = 0x00000337 | ((functionEntry
<< 12) & 0x000000000ffff000);
635 // load vtableOffset to t5
636 *p
++ = 0x00000f37 | ((vtableOffset
)&0xfffff000);
637 *p
++ = 0x000f6f13 | ((vtableOffset
<< 20) & 0xfff00000);
638 // jump to privateSnippetExecutor
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
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
;
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:
674 bridges::cpp_uno::shared::VtableFactory::Slot
*
675 bridges::cpp_uno::shared::VtableFactory::initializeBlock(void* block
, sal_Int32 slotCount
,
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
;
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
]);
702 switch (member
->eTypeClass
)
704 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
706 (s
++)->fn
= code
+ writetoexecdiff
;
708 code
, functionOffset
++, vtableOffset
,
709 CPPU_CURRENT_NAMESPACE::return_in_hidden_param(
710 reinterpret_cast<typelib_InterfaceAttributeTypeDescription
*>(member
)
711 ->pAttributeTypeRef
));
714 if (!reinterpret_cast<typelib_InterfaceAttributeTypeDescription
*>(member
)
717 (s
++)->fn
= code
+ writetoexecdiff
;
718 code
= codeSnippet(code
, functionOffset
++, vtableOffset
, false);
722 case typelib_TypeClass_INTERFACE_METHOD
:
723 (s
++)->fn
= code
+ writetoexecdiff
;
725 code
, functionOffset
++, vtableOffset
,
726 CPPU_CURRENT_NAMESPACE::return_in_hidden_param(
727 reinterpret_cast<typelib_InterfaceMethodTypeDescription
*>(member
)
735 TYPELIB_DANGER_RELEASE(member
);
740 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */