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