xref: /trunk/main/bridges/source/cpp_uno/s5abi_macosx_x86-64/cpp2uno.cxx (revision 69f2ccfa9e97a7c1792bfba86fc6ebca4ddba1a0)
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.
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 = (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 = (sal_Int32 *)(pUnoArgs + (2 * nParams));
109     // type descriptions for reconversions
110     typelib_TypeDescription ** ppTempParamTypeDescr = (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             *(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 //==================================================================================================
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                               (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 //==================================================================================================
395 extern "C" void privateSnippetExecutor( void )
396 {
397     asm volatile (
398     "\t"
399     "subq   $160, %%rsp\n\t"
400     "movq   %%r10, -152(%%rbp)\n\t"     // Save (nVtableOffset << 32) + nFunctionIndex
401 
402     "movq   %%rdi, -112(%%rbp)\n\t"     // Save GP registers
403     "movq   %%rsi, -104(%%rbp)\n\t"
404     "movq   %%rdx, -96(%%rbp)\n\t"
405     "movq   %%rcx, -88(%%rbp)\n\t"
406     "movq   %%r8 , -80(%%rbp)\n\t"
407     "movq   %%r9 , -72(%%rbp)\n\t"
408 
409     "movsd  %%xmm0, -64(%%rbp)\n\t"     // Save FP registers
410     "movsd  %%xmm1, -56(%%rbp)\n\t"
411     "movsd  %%xmm2, -48(%%rbp)\n\t"
412     "movsd  %%xmm3, -40(%%rbp)\n\t"
413     "movsd  %%xmm4, -32(%%rbp)\n\t"
414     "movsd  %%xmm5, -24(%%rbp)\n\t"
415     "movsd  %%xmm6, -16(%%rbp)\n\t"
416     "movsd  %%xmm7, -8(%%rbp)\n\t"
417 
418     "leaq   -144(%%rbp), %%r9\n\t"      // 6th param: sal_uInt64* pRegisterReturn
419     "leaq   16(%%rbp), %%r8\n\t"        // 5rd param: void** ovrflw
420     "leaq   -64(%%rbp), %%rcx\n\t"      // 4th param: void** fpreg
421     "leaq   -112(%%rbp), %%rdx\n\t"     // 3rd param: void** gpreg
422     "movl   -148(%%rbp), %%esi\n\t"     // 2nd param: sal_int32 nVtableOffset
423     "movl   -152(%%rbp), %%edi\n\t"     // 1st param: sal_int32 nFunctionIndex
424 
425     "call   _cpp_vtable_call\n\t"
426 
427     "cmp    $10, %%rax\n\t"             // typelib_TypeClass_FLOAT
428     "je .Lfloat\n\t"
429     "cmp    $11, %%rax\n\t"             // typelib_TypeClass_DOUBLE
430     "je .Lfloat\n\t"
431 
432     "movq   -144(%%rbp), %%rax\n\t"     // Return value (int case)
433     "movq   -136(%%rbp), %%rdx\n\t"     // Return value (int case)
434     "movq   -144(%%rbp), %%xmm0\n\t"    // Return value (int case)
435     "movq   -136(%%rbp), %%xmm1\n\t"    // Return value (int case)
436     "jmp    .Lfinish\n"
437 ".Lfloat:\n\t"
438     "movlpd -144(%%rbp), %%xmm0\n"      // Return value (float/double case)
439 ".Lfinish:\n\t"
440     "addq   $160, %%rsp\n"
441     :
442     :
443     : "rax", "r10", "xmm0" );
444 }
445 const int codeSnippetSize = 24;
446 
447 // Generate a trampoline that redirects method calls to
448 // privateSnippetExecutor().
449 //
450 // privateSnippetExecutor() saves all the registers that are used for
451 // parameter passing on x86_64, and calls the cpp_vtable_call().
452 // When it returns, privateSnippetExecutor() sets the return value.
453 //
454 // Note: The code snippet we build here must not create a stack frame,
455 // otherwise the UNO exceptions stop working thanks to non-existing
456 // unwinding info.
457 unsigned char * codeSnippet( unsigned char * code,
458         sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
459         bool bHasHiddenParam ) SAL_THROW( () )
460 {
461     sal_uInt64 nOffsetAndIndex = ( ( (sal_uInt64) nVtableOffset ) << 32 ) | ( (sal_uInt64) nFunctionIndex );
462 
463     if ( bHasHiddenParam )
464         nOffsetAndIndex |= 0x80000000;
465 
466     // movq $<nOffsetAndIndex>, %r10
467     *reinterpret_cast<sal_uInt16 *>( code ) = 0xba49;
468     *reinterpret_cast<sal_uInt16 *>( code + 2 ) = nOffsetAndIndex & 0xFFFF;
469     *reinterpret_cast<sal_uInt32 *>( code + 4 ) = nOffsetAndIndex >> 16;
470     *reinterpret_cast<sal_uInt16 *>( code + 8 ) = nOffsetAndIndex >> 48;
471 
472     // movq $<address of the privateSnippetExecutor>, %r11
473     *reinterpret_cast<sal_uInt16 *>( code + 10 ) = 0xbb49;
474     *reinterpret_cast<sal_uInt32 *>( code + 12 ) = reinterpret_cast<sal_uInt64>(privateSnippetExecutor);
475     *reinterpret_cast<sal_uInt32 *>( code + 16 ) = reinterpret_cast<sal_uInt64>(privateSnippetExecutor) >> 32;
476 
477     // jmpq *%r11
478     *reinterpret_cast<sal_uInt32 *>( code + 20 ) = 0x00e3ff49;
479 
480     return code + codeSnippetSize;
481 }
482 
483 //==================================================================================================
484 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
485 
486 bridges::cpp_uno::shared::VtableFactory::Slot *
487 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
488 {
489     return static_cast< Slot * >(block) + 2;
490 }
491 
492 //==================================================================================================
493 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
494     sal_Int32 slotCount)
495 {
496     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
497 }
498 
499 //==================================================================================================
500 bridges::cpp_uno::shared::VtableFactory::Slot *
501 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
502     void * block, sal_Int32 slotCount)
503 {
504     Slot * slots = mapBlockToVtable(block);
505     slots[-2].fn = 0;
506     slots[-1].fn = 0;
507     return slots + slotCount;
508 }
509 
510 //==================================================================================================
511 
512 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
513     Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff,
514     typelib_InterfaceTypeDescription const * type, sal_Int32 nFunctionOffset,
515     sal_Int32 functionCount, sal_Int32 nVtableOffset )
516 {
517     (*slots) -= functionCount;
518     Slot * s = *slots;
519     for ( sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos )
520     {
521         typelib_TypeDescription * pTD = 0;
522 
523         TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] );
524         OSL_ASSERT( pTD );
525 
526         if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass )
527         {
528             typelib_InterfaceAttributeTypeDescription *pAttrTD =
529                 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
530 
531             // get method
532             (s++)->fn = code + writetoexecdiff;
533             code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
534                                 x86_64::return_in_hidden_param( pAttrTD->pAttributeTypeRef ) );
535 
536             if ( ! pAttrTD->bReadOnly )
537             {
538                 // set method
539                 (s++)->fn = code + writetoexecdiff;
540                 code = codeSnippet( code, nFunctionOffset++, nVtableOffset, false );
541             }
542         }
543         else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass )
544         {
545             typelib_InterfaceMethodTypeDescription *pMethodTD =
546                 reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
547 
548             (s++)->fn = code + writetoexecdiff;
549             code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
550                                 x86_64::return_in_hidden_param( pMethodTD->pReturnTypeRef ) );
551         }
552         else
553             OSL_ASSERT( false );
554 
555         TYPELIB_DANGER_RELEASE( pTD );
556     }
557     return code;
558 }
559 
560 //==================================================================================================
561 void bridges::cpp_uno::shared::VtableFactory::flushCode(
562     unsigned char const *, unsigned char const * )
563 {
564 }
565