1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_bridges.hxx"
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <hash_map>
30
31 #include <rtl/alloc.h>
32 #include <osl/mutex.hxx>
33
34 #include <com/sun/star/uno/genfunc.hxx>
35 #include "com/sun/star/uno/RuntimeException.hpp"
36 #include <uno/data.h>
37 #include <typelib/typedescription.hxx>
38
39 #include "bridges/cpp_uno/shared/bridge.hxx"
40 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
41 #include "bridges/cpp_uno/shared/types.hxx"
42 #include "bridges/cpp_uno/shared/vtablefactory.hxx"
43
44 #include "abi.hxx"
45 #include "share.hxx"
46
47 using namespace ::osl;
48 using namespace ::rtl;
49 using namespace ::com::sun::star::uno;
50
51 //==================================================================================================
52
53 // Perform the UNO call
54 //
55 // We must convert the parameters stored in gpreg, fpreg and ovrflw to UNO
56 // arguments and call pThis->getUnoI()->pDispatcher.
57 //
58 // gpreg: this, [gpr params x0..x7] (the indirect-result ptr is x8, separate)
59 // fpreg: [fpr params d0..d7]
60 // ovrflw: [gpr or fpr params (properly aligned)]
61 //
62 // On AArch64 a structure bigger than 16 bytes is returned via the buffer
63 // addressed by x8 (pIndirectReturn); 'this' is always x0 = gpreg[0].
64 // Simple types are returned in x0,x1 (int) or d0,d1 (fp); HFAs in d0..d3;
65 // non-HFA structures <= 16 bytes in x0,x1.
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,void * pIndirectReturn,sal_uInt64 * pRegisterReturn)66 static typelib_TypeClass cpp2uno_call(
67 bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
68 const typelib_TypeDescription * pMemberTypeDescr,
69 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
70 sal_Int32 nParams, typelib_MethodParameter * pParams,
71 void ** gpreg, void ** fpreg, void ** ovrflw,
72 void * pIndirectReturn, // AArch64 x8 indirect-result pointer (0 if none)
73 sal_uInt64 * pRegisterReturn /* space for register return */ )
74 {
75 unsigned int nr_gpr = 0; //number of gpr registers used
76 unsigned int nr_fpr = 0; //number of fpr registers used
77
78 // return
79 typelib_TypeDescription * pReturnTypeDescr = 0;
80 if (pReturnTypeRef)
81 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
82
83 void * pUnoReturn = 0;
84 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
85
86 if ( pReturnTypeDescr )
87 {
88 if ( aarch64::return_in_hidden_param( pReturnTypeRef ) )
89 {
90 // AArch64: the indirect-result pointer arrives in x8, NOT in the
91 // first general-purpose argument register (unlike x86-64 SysV).
92 // So we take it from pIndirectReturn and do NOT consume a gpreg
93 // slot here; 'this' still occupies gpreg[0] below.
94 pCppReturn = pIndirectReturn;
95
96 pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
97 ? alloca( pReturnTypeDescr->nSize )
98 : pCppReturn ); // direct way
99 }
100 else
101 pUnoReturn = pRegisterReturn; // direct way for simple types
102 }
103
104 // pop this (x0)
105 gpreg++;
106 nr_gpr++;
107
108 // stack space
109 // parameters
110 void ** pUnoArgs = reinterpret_cast<void **>(alloca( 4 * sizeof(void *) * nParams ));
111 void ** pCppArgs = pUnoArgs + nParams;
112 // indizes of values this have to be converted (interface conversion cpp<=>uno)
113 sal_Int32 * pTempIndizes = reinterpret_cast<sal_Int32 *>(pUnoArgs + (2 * nParams));
114 // type descriptions for reconversions
115 typelib_TypeDescription ** ppTempParamTypeDescr = reinterpret_cast<typelib_TypeDescription **>(pUnoArgs + (3 * nParams));
116
117 sal_Int32 nTempIndizes = 0;
118
119 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
120 {
121 const typelib_MethodParameter & rParam = pParams[nPos];
122
123 int nUsedGPR = 0;
124 int nUsedFPR = 0;
125 bool bFitsRegisters = aarch64::examine_argument( rParam.pTypeRef, false, nUsedGPR, nUsedFPR );
126 if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( rParam.pTypeRef ) ) // value
127 {
128 // A simple UNO type occupies exactly one register, GPR or FPR.
129 OSL_ASSERT( bFitsRegisters && ( ( nUsedFPR == 1 && nUsedGPR == 0 ) || ( nUsedFPR == 0 && nUsedGPR == 1 ) ) );
130
131 if ( nUsedFPR == 1 )
132 {
133 if ( nr_fpr < aarch64::MAX_FPR_REGS )
134 {
135 pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++;
136 nr_fpr++;
137 }
138 else
139 pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
140 }
141 else if ( nUsedGPR == 1 )
142 {
143 if ( nr_gpr < aarch64::MAX_GPR_REGS )
144 {
145 pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++;
146 nr_gpr++;
147 }
148 else
149 pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
150 }
151 }
152 else // struct <= 16 bytes || ptr to complex value || ref
153 {
154 typelib_TypeDescription * pParamTypeDescr = 0;
155 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
156
157 void *pCppStack;
158 if ( nr_gpr < aarch64::MAX_GPR_REGS )
159 {
160 pCppArgs[nPos] = pCppStack = *gpreg++;
161 nr_gpr++;
162 }
163 else
164 pCppArgs[nPos] = pCppStack = *ovrflw++;
165
166 if (! rParam.bIn) // is pure out
167 {
168 // uno out is unconstructed mem!
169 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
170 pTempIndizes[nTempIndizes] = nPos;
171 // will be released at reconversion
172 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
173 }
174 else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ) ) // is in/inout
175 {
176 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
177 pCppStack, pParamTypeDescr,
178 pThis->getBridge()->getCpp2Uno() );
179 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
180 // will be released at reconversion
181 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
182 }
183 else // direct way
184 {
185 pUnoArgs[nPos] = pCppStack;
186 // no longer needed
187 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
188 }
189 }
190 }
191
192 // ExceptionHolder
193 uno_Any aUnoExc; // Any will be constructed by callee
194 uno_Any * pUnoExc = &aUnoExc;
195
196 // invoke uno dispatch call
197 (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
198
199 // in case an exception occurred...
200 if ( pUnoExc )
201 {
202 // destruct temporary in/inout params
203 for ( ; nTempIndizes--; )
204 {
205 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
206
207 if (pParams[nIndex].bIn) // is in/inout => was constructed
208 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
209 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
210 }
211 if (pReturnTypeDescr)
212 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
213
214 CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
215 // is here for dummy
216 return typelib_TypeClass_VOID;
217 }
218 else // else no exception occurred...
219 {
220 // temporary params
221 for ( ; nTempIndizes--; )
222 {
223 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
224 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
225
226 if ( pParams[nIndex].bOut ) // inout/out
227 {
228 // convert and assign
229 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
230 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
231 pThis->getBridge()->getUno2Cpp() );
232 }
233 // destroy temp uno param
234 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
235
236 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
237 }
238 // return
239 if ( pCppReturn ) // has complex return
240 {
241 if ( pUnoReturn != pCppReturn ) // needs reconversion
242 {
243 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
244 pThis->getBridge()->getUno2Cpp() );
245 // destroy temp uno return
246 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
247 }
248 // complex return ptr is set to return reg
249 *reinterpret_cast<void **>(pRegisterReturn) = pCppReturn;
250 }
251 if ( pReturnTypeDescr )
252 {
253 typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
254 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
255 return eRet;
256 }
257 else
258 return typelib_TypeClass_VOID;
259 }
260 }
261
262
263 //==================================================================================================
cpp_vtable_call(sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,void ** gpreg,void ** fpreg,void ** ovrflw,void * pIndirectReturn,sal_uInt64 * pRegisterReturn)264 extern "C" typelib_TypeClass cpp_vtable_call(
265 sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
266 void ** gpreg, void ** fpreg, void ** ovrflw,
267 void * pIndirectReturn, // AArch64 x8 indirect-result pointer (0 if none)
268 sal_uInt64 * pRegisterReturn /* space for register return */ )
269 {
270 // gpreg: this, [other gpr params x0..x7]
271 // fpreg: [fpr params d0..d7]
272 // ovrflw: [gpr or fpr params (properly aligned)]
273 // pIndirectReturn: x8 (the hidden return buffer), when bit 0x80000000 set.
274 //
275 // On AArch64 'this' is ALWAYS x0 = gpreg[0]; the hidden return pointer is
276 // the separate x8 register, not a displaced first GPR (unlike x86-64 SysV
277 // where it occupied gpreg[0] and 'this' moved to gpreg[1]).
278 if ( nFunctionIndex & 0x80000000 )
279 nFunctionIndex &= 0x7fffffff;
280
281 void * pThis = gpreg[0];
282 pThis = static_cast<char *>( pThis ) - nVtableOffset;
283
284 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
285 bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis );
286
287 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
288
289 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!\n" );
290 if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex )
291 {
292 throw RuntimeException( OUString::createFromAscii("illegal vtable index!"),
293 reinterpret_cast<XInterface *>( pCppI ) );
294 }
295
296 // determine called method
297 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
298 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!\n" );
299
300 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
301
302 typelib_TypeClass eRet;
303 switch ( aMemberDescr.get()->eTypeClass )
304 {
305 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
306 {
307 typelib_TypeDescriptionReference *pAttrTypeRef =
308 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef;
309
310 if ( pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
311 {
312 // is GET method
313 eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef,
314 0, 0, // no params
315 gpreg, fpreg, ovrflw, pIndirectReturn, pRegisterReturn );
316 }
317 else
318 {
319 // is SET method
320 typelib_MethodParameter aParam;
321 aParam.pTypeRef = pAttrTypeRef;
322 aParam.bIn = sal_True;
323 aParam.bOut = sal_False;
324
325 eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
326 0, // indicates void return
327 1, &aParam,
328 gpreg, fpreg, ovrflw, pIndirectReturn, pRegisterReturn );
329 }
330 break;
331 }
332 case typelib_TypeClass_INTERFACE_METHOD:
333 {
334 // is METHOD
335 switch ( nFunctionIndex )
336 {
337 case 1: // acquire()
338 pCppI->acquireProxy(); // non virtual call!
339 eRet = typelib_TypeClass_VOID;
340 break;
341 case 2: // release()
342 pCppI->releaseProxy(); // non virtual call!
343 eRet = typelib_TypeClass_VOID;
344 break;
345 case 0: // queryInterface() opt
346 {
347 // queryInterface([in] type) returns an Any (> 16 bytes),
348 // so on AArch64 the result buffer is x8 (pIndirectReturn),
349 // 'this' is gpreg[0], and the type argument is the first
350 // real parameter, gpreg[1].
351 typelib_TypeDescription * pTD = 0;
352 TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( gpreg[1] )->getTypeLibType() );
353 if ( pTD )
354 {
355 XInterface * pInterface = 0;
356 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
357 ( pCppI->getBridge()->getCppEnv(),
358 reinterpret_cast<void **>(&pInterface),
359 pCppI->getOid().pData,
360 reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
361
362 if ( pInterface )
363 {
364 ::uno_any_construct( reinterpret_cast<uno_Any *>( pIndirectReturn ),
365 &pInterface, pTD, cpp_acquire );
366
367 pInterface->release();
368 TYPELIB_DANGER_RELEASE( pTD );
369
370 reinterpret_cast<void **>( pRegisterReturn )[0] = pIndirectReturn;
371 eRet = typelib_TypeClass_ANY;
372 break;
373 }
374 TYPELIB_DANGER_RELEASE( pTD );
375 }
376 } // else perform queryInterface()
377 default:
378 {
379 typelib_InterfaceMethodTypeDescription *pMethodTD =
380 reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
381
382 eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
383 pMethodTD->pReturnTypeRef,
384 pMethodTD->nParams,
385 pMethodTD->pParams,
386 gpreg, fpreg, ovrflw, pIndirectReturn, pRegisterReturn );
387 }
388 }
389 break;
390 }
391 default:
392 {
393 throw RuntimeException( OUString::createFromAscii("no member description found!"),
394 reinterpret_cast<XInterface *>( pCppI ) );
395 // is here for dummy
396 eRet = typelib_TypeClass_VOID;
397 }
398 }
399
400 return eRet;
401 }
402
403 //==================================================================================================
404 // The incoming register-spill executor, implemented in call.s. It is reached
405 // via BR from a per-slot snippet (codeSnippet below) with x16 carrying the
406 // packed (nVtableOffset << 32) | nFunctionIndex; it spills the argument
407 // registers and calls cpp_vtable_call.
408 extern "C" void privateSnippetExecutor( void );
409
410 // Each snippet is 5 AArch64 instructions (20 bytes) + 4 bytes padding to an
411 // 8-byte boundary + two 8-byte literals (the packed index and the executor
412 // address) = 40 bytes.
413 const int codeSnippetSize = 40;
414
415 // Generate a per-vtable-slot trampoline that loads the packed function index
416 // into x16 and branches to privateSnippetExecutor(), preserving every
417 // argument register. Uses PC-relative literal loads because AArch64 cannot
418 // embed a 64-bit immediate in a single instruction.
419 //
420 // Layout (offsets in bytes from code):
421 // 0: ldr x16, #24 ; x16 = nOffsetAndIndex (literal at +24)
422 // 4: ldr x17, #28 ; x17 = privateSnippetExecutor (literal at +32)
423 // 8: br x17
424 // 12: (unused / padding)
425 // 16: (padding to 8-byte align the literals at 24)
426 // 24: .quad nOffsetAndIndex
427 // 32: .quad privateSnippetExecutor
428 //
429 // Note: the snippet creates no stack frame, so the C++ unwinder walks straight
430 // through it to the original caller (required for UNO exception propagation).
codeSnippet(unsigned char * code,sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,bool bHasHiddenParam)431 unsigned char * codeSnippet( unsigned char * code,
432 sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
433 bool bHasHiddenParam ) SAL_THROW( () )
434 {
435 sal_uInt64 nOffsetAndIndex = ( static_cast<sal_uInt64>( nVtableOffset ) << 32 ) | static_cast<sal_uInt64>( nFunctionIndex );
436
437 if ( bHasHiddenParam )
438 nOffsetAndIndex |= 0x80000000;
439
440 sal_uInt32 * p = reinterpret_cast<sal_uInt32 *>( code );
441
442 // ldr x16, #24 -> literal at code+24. imm19 = 24/4 = 6.
443 // encoding: 0x58000000 | (imm19 << 5) | Rt(16)
444 p[0] = 0x58000000 | ( 6 << 5 ) | 16;
445 // ldr x17, #28 -> literal at code+32 (relative to this insn at +4): 28.
446 // imm19 = 28/4 = 7.
447 p[1] = 0x58000000 | ( 7 << 5 ) | 17;
448 // br x17 -> 0xD61F0000 | (Rn(17) << 5)
449 p[2] = 0xD61F0000 | ( 17 << 5 );
450 // p[3] (offset 12) and p[4] (offset 16..20) are padding.
451 p[3] = 0xD503201F; // NOP
452 p[4] = 0xD503201F; // NOP
453
454 // literals, 8-byte aligned at offset 24 and 32
455 *reinterpret_cast<sal_uInt64 *>( code + 24 ) = nOffsetAndIndex;
456 *reinterpret_cast<sal_uInt64 *>( code + 32 ) = reinterpret_cast<sal_uInt64>( privateSnippetExecutor );
457
458 return code + codeSnippetSize;
459 }
460
461 //==================================================================================================
462 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
463
464 bridges::cpp_uno::shared::VtableFactory::Slot *
mapBlockToVtable(void * block)465 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
466 {
467 return static_cast< Slot * >(block) + 2;
468 }
469
470 //==================================================================================================
getBlockSize(sal_Int32 slotCount)471 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
472 sal_Int32 slotCount)
473 {
474 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
475 }
476
477 //==================================================================================================
478 bridges::cpp_uno::shared::VtableFactory::Slot *
initializeBlock(void * block,sal_Int32 slotCount)479 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
480 void * block, sal_Int32 slotCount)
481 {
482 Slot * slots = mapBlockToVtable(block);
483 slots[-2].fn = 0;
484 slots[-1].fn = 0;
485 return slots + slotCount;
486 }
487
488 //==================================================================================================
489
addLocalFunctions(Slot ** slots,unsigned char * code,typelib_InterfaceTypeDescription const * type,sal_Int32 nFunctionOffset,sal_Int32 functionCount,sal_Int32 nVtableOffset)490 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
491 Slot ** slots, unsigned char * code, /*sal_PtrDiff writetoexecdiff,*/
492 typelib_InterfaceTypeDescription const * type, sal_Int32 nFunctionOffset,
493 sal_Int32 functionCount, sal_Int32 nVtableOffset )
494 {
495 const sal_PtrDiff writetoexecdiff = 0;
496 (*slots) -= functionCount;
497 Slot * s = *slots;
498 for ( sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos )
499 {
500 typelib_TypeDescription * pTD = 0;
501
502 TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] );
503 OSL_ASSERT( pTD );
504
505 if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass )
506 {
507 typelib_InterfaceAttributeTypeDescription *pAttrTD =
508 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
509
510 // get method
511 (s++)->fn = code + writetoexecdiff;
512 code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
513 aarch64::return_in_hidden_param( pAttrTD->pAttributeTypeRef ) );
514
515 if ( ! pAttrTD->bReadOnly )
516 {
517 // set method
518 (s++)->fn = code + writetoexecdiff;
519 code = codeSnippet( code, nFunctionOffset++, nVtableOffset, false );
520 }
521 }
522 else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass )
523 {
524 typelib_InterfaceMethodTypeDescription *pMethodTD =
525 reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
526
527 (s++)->fn = code + writetoexecdiff;
528 code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
529 aarch64::return_in_hidden_param( pMethodTD->pReturnTypeRef ) );
530 }
531 else
532 OSL_ASSERT( false );
533
534 TYPELIB_DANGER_RELEASE( pTD );
535 }
536 return code;
537 }
538
539 //==================================================================================================
flushCode(unsigned char const *,unsigned char const *)540 void bridges::cpp_uno::shared::VtableFactory::flushCode(
541 unsigned char const *, unsigned char const * )
542 {
543 }
544