xref: /AOO41X/main/bridges/source/cpp_uno/s5abi_macosx_x86-64/cpp2uno.cxx (revision 67a794bc92a1e8ffd80bf2fdc9bf74ed09144659)
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 paramaters stored in gpreg, fpreg and ovrflw to UNO
56 // arguments and call pThis->getUnoI()->pDispatcher.
57 //
58 // gpreg:  [ret *], this, [gpr params]
59 // fpreg:  [fpr params]
60 // ovrflw: [gpr or fpr params (properly aligned)]
61 //
62 // [ret *] is present when we are returning a structure bigger than 16 bytes
63 // Simple types are returned in rax, rdx (int), or xmm0, xmm1 (fp).
64 // Similarly structures <= 16 bytes are in rax, rdx, xmm0, xmm1 as necessary.
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)65 static typelib_TypeClass cpp2uno_call(
66     bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
67     const typelib_TypeDescription * pMemberTypeDescr,
68     typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
69     sal_Int32 nParams, typelib_MethodParameter * pParams,
70     void ** gpreg, void ** fpreg, void ** ovrflw,
71     sal_uInt64 * pRegisterReturn /* space for register return */ )
72 {
73     unsigned int nr_gpr = 0; //number of gpr registers used
74     unsigned int nr_fpr = 0; //number of fpr registers used
75 
76     // return
77     typelib_TypeDescription * pReturnTypeDescr = 0;
78     if (pReturnTypeRef)
79         TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
80 
81     void * pUnoReturn = 0;
82     void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
83 
84     if ( pReturnTypeDescr )
85     {
86         if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
87         {
88             pCppReturn = *gpreg++;
89             nr_gpr++;
90 
91             pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
92                            ? alloca( pReturnTypeDescr->nSize )
93                            : pCppReturn ); // direct way
94         }
95         else
96             pUnoReturn = pRegisterReturn; // direct way for simple types
97     }
98 
99     // pop this
100     gpreg++;
101     nr_gpr++;
102 
103     // stack space
104     // parameters
105     void ** pUnoArgs = reinterpret_cast<void **>(alloca( 4 * sizeof(void *) * nParams ));
106     void ** pCppArgs = pUnoArgs + nParams;
107     // indizes of values this have to be converted (interface conversion cpp<=>uno)
108     sal_Int32 * pTempIndizes = reinterpret_cast<sal_Int32 *>(pUnoArgs + (2 * nParams));
109     // type descriptions for reconversions
110     typelib_TypeDescription ** ppTempParamTypeDescr = reinterpret_cast<typelib_TypeDescription **>(pUnoArgs + (3 * nParams));
111 
112     sal_Int32 nTempIndizes = 0;
113 
114     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
115     {
116         const typelib_MethodParameter & rParam = pParams[nPos];
117 
118         int nUsedGPR = 0;
119         int nUsedSSE = 0;
120         bool bFitsRegisters = x86_64::examine_argument( rParam.pTypeRef, false, nUsedGPR, nUsedSSE );
121         if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( rParam.pTypeRef ) ) // value
122         {
123             // Simple types must fit exactly one register on x86_64
124             OSL_ASSERT( bFitsRegisters && ( ( nUsedSSE == 1 && nUsedGPR == 0 ) || ( nUsedSSE == 0 && nUsedGPR == 1 ) ) );
125 
126             if ( nUsedSSE == 1 )
127             {
128                 if ( nr_fpr < x86_64::MAX_SSE_REGS )
129                 {
130                     pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++;
131                     nr_fpr++;
132                 }
133                 else
134                     pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
135             }
136             else if ( nUsedGPR == 1 )
137             {
138                 if ( nr_gpr < x86_64::MAX_GPR_REGS )
139                 {
140                     pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++;
141                     nr_gpr++;
142                 }
143                 else
144                     pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
145             }
146         }
147         else // struct <= 16 bytes || ptr to complex value || ref
148         {
149             typelib_TypeDescription * pParamTypeDescr = 0;
150             TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
151 
152             void *pCppStack;
153             if ( nr_gpr < x86_64::MAX_GPR_REGS )
154             {
155                 pCppArgs[nPos] = pCppStack = *gpreg++;
156                 nr_gpr++;
157             }
158             else
159                 pCppArgs[nPos] = pCppStack = *ovrflw++;
160 
161             if (! rParam.bIn) // is pure out
162             {
163                 // uno out is unconstructed mem!
164                 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
165                 pTempIndizes[nTempIndizes] = nPos;
166                 // will be released at reconversion
167                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
168             }
169             else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ) ) // is in/inout
170             {
171                 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
172                                         pCppStack, pParamTypeDescr,
173                                         pThis->getBridge()->getCpp2Uno() );
174                 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
175                 // will be released at reconversion
176                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
177             }
178             else // direct way
179             {
180                 pUnoArgs[nPos] = pCppStack;
181                 // no longer needed
182                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
183             }
184         }
185     }
186 
187     // ExceptionHolder
188     uno_Any aUnoExc; // Any will be constructed by callee
189     uno_Any * pUnoExc = &aUnoExc;
190 
191     // invoke uno dispatch call
192     (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
193 
194     // in case an exception occurred...
195     if ( pUnoExc )
196     {
197         // destruct temporary in/inout params
198         for ( ; nTempIndizes--; )
199         {
200             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
201 
202             if (pParams[nIndex].bIn) // is in/inout => was constructed
203                 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
204             TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
205         }
206         if (pReturnTypeDescr)
207             TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
208 
209         CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
210         // is here for dummy
211         return typelib_TypeClass_VOID;
212     }
213     else // else no exception occurred...
214     {
215         // temporary params
216         for ( ; nTempIndizes--; )
217         {
218             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
219             typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
220 
221             if ( pParams[nIndex].bOut ) // inout/out
222             {
223                 // convert and assign
224                 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
225                 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
226                                         pThis->getBridge()->getUno2Cpp() );
227             }
228             // destroy temp uno param
229             uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
230 
231             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
232         }
233         // return
234         if ( pCppReturn ) // has complex return
235         {
236             if ( pUnoReturn != pCppReturn ) // needs reconversion
237             {
238                 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
239                                         pThis->getBridge()->getUno2Cpp() );
240                 // destroy temp uno return
241                 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
242             }
243             // complex return ptr is set to return reg
244             *reinterpret_cast<void **>(pRegisterReturn) = pCppReturn;
245         }
246         if ( pReturnTypeDescr )
247         {
248             typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
249             TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
250             return eRet;
251         }
252         else
253             return typelib_TypeClass_VOID;
254     }
255 }
256 
257 
258 //==================================================================================================
cpp_vtable_call(sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,void ** gpreg,void ** fpreg,void ** ovrflw,sal_uInt64 * pRegisterReturn)259 extern "C" typelib_TypeClass cpp_vtable_call(
260     sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
261     void ** gpreg, void ** fpreg, void ** ovrflw,
262     sal_uInt64 * pRegisterReturn /* space for register return */ )
263 {
264     // gpreg:  [ret *], this, [other gpr params]
265     // fpreg:  [fpr params]
266     // ovrflw: [gpr or fpr params (properly aligned)]
267     void * pThis;
268     if ( nFunctionIndex & 0x80000000 )
269     {
270         nFunctionIndex &= 0x7fffffff;
271         pThis = gpreg[1];
272     }
273     else
274     {
275         pThis = gpreg[0];
276     }
277     pThis = static_cast<char *>( pThis ) - nVtableOffset;
278 
279     bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
280         bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis );
281 
282     typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
283 
284     OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!\n" );
285     if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex )
286     {
287         throw RuntimeException( OUString::createFromAscii("illegal vtable index!"),
288                                 reinterpret_cast<XInterface *>( pCppI ) );
289     }
290 
291     // determine called method
292     sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
293     OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!\n" );
294 
295     TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
296 
297     typelib_TypeClass eRet;
298     switch ( aMemberDescr.get()->eTypeClass )
299     {
300         case typelib_TypeClass_INTERFACE_ATTRIBUTE:
301         {
302             typelib_TypeDescriptionReference *pAttrTypeRef =
303                 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef;
304 
305             if ( pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
306             {
307                 // is GET method
308                 eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef,
309                         0, 0, // no params
310                         gpreg, fpreg, ovrflw, pRegisterReturn );
311             }
312             else
313             {
314                 // is SET method
315                 typelib_MethodParameter aParam;
316                 aParam.pTypeRef = pAttrTypeRef;
317                 aParam.bIn      = sal_True;
318                 aParam.bOut     = sal_False;
319 
320                 eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
321                         0, // indicates void return
322                         1, &aParam,
323                         gpreg, fpreg, ovrflw, pRegisterReturn );
324             }
325             break;
326         }
327         case typelib_TypeClass_INTERFACE_METHOD:
328         {
329             // is METHOD
330             switch ( nFunctionIndex )
331             {
332                 case 1: // acquire()
333                     pCppI->acquireProxy(); // non virtual call!
334                     eRet = typelib_TypeClass_VOID;
335                     break;
336                 case 2: // release()
337                     pCppI->releaseProxy(); // non virtual call!
338                     eRet = typelib_TypeClass_VOID;
339                     break;
340                 case 0: // queryInterface() opt
341                 {
342                     typelib_TypeDescription * pTD = 0;
343                     TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( gpreg[2] )->getTypeLibType() );
344                     if ( pTD )
345                     {
346                         XInterface * pInterface = 0;
347                         (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
348                             ( pCppI->getBridge()->getCppEnv(),
349                               reinterpret_cast<void **>(&pInterface),
350                               pCppI->getOid().pData,
351                               reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
352 
353                         if ( pInterface )
354                         {
355                             ::uno_any_construct( reinterpret_cast<uno_Any *>( gpreg[0] ),
356                                                  &pInterface, pTD, cpp_acquire );
357 
358                             pInterface->release();
359                             TYPELIB_DANGER_RELEASE( pTD );
360 
361                             reinterpret_cast<void **>( pRegisterReturn )[0] = gpreg[0];
362                             eRet = typelib_TypeClass_ANY;
363                             break;
364                         }
365                         TYPELIB_DANGER_RELEASE( pTD );
366                     }
367                 } // else perform queryInterface()
368                 default:
369                 {
370                     typelib_InterfaceMethodTypeDescription *pMethodTD =
371                         reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
372 
373                     eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
374                                          pMethodTD->pReturnTypeRef,
375                                          pMethodTD->nParams,
376                                          pMethodTD->pParams,
377                                          gpreg, fpreg, ovrflw, pRegisterReturn );
378                 }
379             }
380             break;
381         }
382         default:
383         {
384             throw RuntimeException( OUString::createFromAscii("no member description found!"),
385                                     reinterpret_cast<XInterface *>( pCppI ) );
386             // is here for dummy
387             eRet = typelib_TypeClass_VOID;
388         }
389     }
390 
391     return eRet;
392 }
393 
394 //==================================================================================================
privateSnippetExecutor(void)395 extern "C" void privateSnippetExecutor( void )
396 {
397     asm volatile (
398         "   subq    $160, %rsp\n"
399         "   movq    %r10, -152(%rbp)\n"     // Save (nVtableOffset << 32) + nFunctionIndex
400 
401         "   movq    %rdi, -112(%rbp)\n"     // Save GP registers
402         "   movq    %rsi, -104(%rbp)\n"
403         "   movq    %rdx, -96(%rbp)\n"
404         "   movq    %rcx, -88(%rbp)\n"
405         "   movq    %r8 , -80(%rbp)\n"
406         "   movq    %r9 , -72(%rbp)\n"
407 
408         "   movsd   %xmm0, -64(%rbp)\n"     // Save FP registers
409         "   movsd   %xmm1, -56(%rbp)\n"
410         "   movsd   %xmm2, -48(%rbp)\n"
411         "   movsd   %xmm3, -40(%rbp)\n"
412         "   movsd   %xmm4, -32(%rbp)\n"
413         "   movsd   %xmm5, -24(%rbp)\n"
414         "   movsd   %xmm6, -16(%rbp)\n"
415         "   movsd   %xmm7, -8(%rbp)\n"
416 
417         "   leaq    -144(%rbp), %r9\n"      // 6th param: sal_uInt64* pRegisterReturn
418         "   leaq    16(%rbp),   %r8\n"      // 5rd param: void** ovrflw
419         "   leaq    -64(%rbp),  %rcx\n"     // 4th param: void** fpreg
420         "   leaq    -112(%rbp), %rdx\n"     // 3rd param: void** gpreg
421         "   movl    -148(%rbp), %esi\n"     // 2nd param: sal_int32 nVtableOffset
422         "   movl    -152(%rbp), %edi\n"     // 1st param: sal_int32 nFunctionIndex
423 
424         "   call    _cpp_vtable_call\n"
425 
426         "   cmp $10, %rax\n"                // typelib_TypeClass_FLOAT
427         "   je  .Lfloat\n"
428         "   cmp $11, %rax\n"                // typelib_TypeClass_DOUBLE
429         "   je  .Lfloat\n"
430 
431         "   movq    -144(%rbp), %rax\n"     // Return value (int case)
432         "   movq    -136(%rbp), %rdx\n"     // Return value (int case)
433         "   movq    -144(%rbp), %xmm0\n"    // Return value (int case)
434         "   movq    -136(%rbp), %xmm1\n"    // Return value (int case)
435         "   jmp .Lfinish\n"
436         ".Lfloat:\n"
437         "   movlpd  -144(%rbp), %xmm0\n"        // Return value (float/double case)
438         ".Lfinish:\n"
439         "   addq    $160, %rsp\n"
440     );
441 }
442 const int codeSnippetSize = 24;
443 
444 // Generate a trampoline that redirects method calls to
445 // privateSnippetExecutor().
446 //
447 // privateSnippetExecutor() saves all the registers that are used for
448 // parameter passing on x86_64, and calls the cpp_vtable_call().
449 // When it returns, privateSnippetExecutor() sets the return value.
450 //
451 // Note: The code snippet we build here must not create a stack frame,
452 // otherwise the UNO exceptions stop working thanks to non-existing
453 // unwinding info.
codeSnippet(unsigned char * code,sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,bool bHasHiddenParam)454 unsigned char * codeSnippet( unsigned char * code,
455         sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
456         bool bHasHiddenParam ) SAL_THROW( () )
457 {
458     sal_uInt64 nOffsetAndIndex = ( static_cast<sal_uInt64>( nVtableOffset ) << 32 ) | static_cast<sal_uInt64>( nFunctionIndex );
459 
460     if ( bHasHiddenParam )
461         nOffsetAndIndex |= 0x80000000;
462 
463     // movq $<nOffsetAndIndex>, %r10
464     *reinterpret_cast<sal_uInt16 *>( code ) = 0xba49;
465     *reinterpret_cast<sal_uInt64 *>( code + 2 ) = nOffsetAndIndex;
466 
467     // movq $<address of the privateSnippetExecutor>, %r11
468     *reinterpret_cast<sal_uInt16 *>( code + 10 ) = 0xbb49;
469     *reinterpret_cast<sal_uInt64 *>( code + 12 ) = reinterpret_cast<sal_uInt64>( privateSnippetExecutor );
470 
471     // jmpq *%r11
472     *reinterpret_cast<sal_uInt32 *>( code + 20 ) = 0x00e3ff49;
473 
474     return code + codeSnippetSize;
475 }
476 
477 //==================================================================================================
478 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
479 
480 bridges::cpp_uno::shared::VtableFactory::Slot *
mapBlockToVtable(void * block)481 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
482 {
483     return static_cast< Slot * >(block) + 2;
484 }
485 
486 //==================================================================================================
getBlockSize(sal_Int32 slotCount)487 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
488     sal_Int32 slotCount)
489 {
490     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
491 }
492 
493 //==================================================================================================
494 bridges::cpp_uno::shared::VtableFactory::Slot *
initializeBlock(void * block,sal_Int32 slotCount)495 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
496     void * block, sal_Int32 slotCount)
497 {
498     Slot * slots = mapBlockToVtable(block);
499     slots[-2].fn = 0;
500     slots[-1].fn = 0;
501     return slots + slotCount;
502 }
503 
504 //==================================================================================================
505 
addLocalFunctions(Slot ** slots,unsigned char * code,typelib_InterfaceTypeDescription const * type,sal_Int32 nFunctionOffset,sal_Int32 functionCount,sal_Int32 nVtableOffset)506 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
507     Slot ** slots, unsigned char * code, /*sal_PtrDiff writetoexecdiff,*/
508     typelib_InterfaceTypeDescription const * type, sal_Int32 nFunctionOffset,
509     sal_Int32 functionCount, sal_Int32 nVtableOffset )
510 {
511     const sal_PtrDiff writetoexecdiff = 0;
512     (*slots) -= functionCount;
513     Slot * s = *slots;
514     for ( sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos )
515     {
516         typelib_TypeDescription * pTD = 0;
517 
518         TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] );
519         OSL_ASSERT( pTD );
520 
521         if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass )
522         {
523             typelib_InterfaceAttributeTypeDescription *pAttrTD =
524                 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
525 
526             // get method
527             (s++)->fn = code + writetoexecdiff;
528             code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
529                                 x86_64::return_in_hidden_param( pAttrTD->pAttributeTypeRef ) );
530 
531             if ( ! pAttrTD->bReadOnly )
532             {
533                 // set method
534                 (s++)->fn = code + writetoexecdiff;
535                 code = codeSnippet( code, nFunctionOffset++, nVtableOffset, false );
536             }
537         }
538         else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass )
539         {
540             typelib_InterfaceMethodTypeDescription *pMethodTD =
541                 reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
542 
543             (s++)->fn = code + writetoexecdiff;
544             code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
545                                 x86_64::return_in_hidden_param( pMethodTD->pReturnTypeRef ) );
546         }
547         else
548             OSL_ASSERT( false );
549 
550         TYPELIB_DANGER_RELEASE( pTD );
551     }
552     return code;
553 }
554 
555 //==================================================================================================
flushCode(unsigned char const *,unsigned char const *)556 void bridges::cpp_uno::shared::VtableFactory::flushCode(
557     unsigned char const *, unsigned char const * )
558 {
559 }
560