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: [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 bool bHasHiddenReturn = (nFunctionIndex & 0x80000000) != 0;
269 if ( bHasHiddenReturn )
270 {
271 nFunctionIndex &= 0x7fffffff;
272 pThis = gpreg[1];
273 }
274 else
275 {
276 pThis = gpreg[0];
277 }
278 pThis = static_cast<char *>( pThis ) - nVtableOffset;
279
280 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
281 bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis );
282
283 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
284
285 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!\n" );
286 if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex )
287 {
288 throw RuntimeException( OUString::createFromAscii("illegal vtable index!"),
289 reinterpret_cast<XInterface *>( pCppI ) );
290 }
291
292 // determine called method
293 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
294 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!\n" );
295
296 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
297
298 typelib_TypeClass eRet;
299 switch ( aMemberDescr.get()->eTypeClass )
300 {
301 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
302 {
303 typelib_TypeDescriptionReference *pAttrTypeRef =
304 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef;
305
306 if ( pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
307 {
308 // is GET method
309 eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef,
310 0, 0, // no params
311 gpreg, fpreg, ovrflw, pRegisterReturn );
312 }
313 else
314 {
315 // is SET method
316 typelib_MethodParameter aParam;
317 aParam.pTypeRef = pAttrTypeRef;
318 aParam.bIn = sal_True;
319 aParam.bOut = sal_False;
320
321 eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
322 0, // indicates void return
323 1, &aParam,
324 gpreg, fpreg, ovrflw, pRegisterReturn );
325 }
326 break;
327 }
328 case typelib_TypeClass_INTERFACE_METHOD:
329 {
330 // is METHOD
331 switch ( nFunctionIndex )
332 {
333 case 1: // acquire()
334 pCppI->acquireProxy(); // non virtual call!
335 eRet = typelib_TypeClass_VOID;
336 break;
337 case 2: // release()
338 pCppI->releaseProxy(); // non virtual call!
339 eRet = typelib_TypeClass_VOID;
340 break;
341 case 0: // queryInterface() opt
342 // The fast path is only valid when a hidden return param is
343 // present, i.e. gpreg[0]=ret, gpreg[1]=this, gpreg[2]=type.
344 // Without it gpreg[2] is not the type arg, so we must NOT take
345 // the shortcut. Note: we deliberately fall through to default
346 // (not break) so the generic queryInterface() is performed and
347 // eRet is always assigned.
348 if ( bHasHiddenReturn )
349 {
350 typelib_TypeDescription * pTD = 0;
351 TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( gpreg[2] )->getTypeLibType() );
352 if ( pTD )
353 {
354 XInterface * pInterface = 0;
355 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
356 ( pCppI->getBridge()->getCppEnv(),
357 reinterpret_cast<void **>(&pInterface),
358 pCppI->getOid().pData,
359 reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
360
361 if ( pInterface )
362 {
363 ::uno_any_construct( reinterpret_cast<uno_Any *>( gpreg[0] ),
364 &pInterface, pTD, cpp_acquire );
365
366 pInterface->release();
367 TYPELIB_DANGER_RELEASE( pTD );
368
369 reinterpret_cast<void **>( pRegisterReturn )[0] = gpreg[0];
370 eRet = typelib_TypeClass_ANY;
371 break;
372 }
373 TYPELIB_DANGER_RELEASE( pTD );
374 }
375 } // else perform queryInterface()
376 default:
377 {
378 typelib_InterfaceMethodTypeDescription *pMethodTD =
379 reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
380
381 eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
382 pMethodTD->pReturnTypeRef,
383 pMethodTD->nParams,
384 pMethodTD->pParams,
385 gpreg, fpreg, ovrflw, pRegisterReturn );
386 }
387 }
388 break;
389 }
390 default:
391 {
392 throw RuntimeException( OUString::createFromAscii("no member description found!"),
393 reinterpret_cast<XInterface *>( pCppI ) );
394 // is here for dummy
395 eRet = typelib_TypeClass_VOID;
396 }
397 }
398
399 return eRet;
400 }
401
402 //==================================================================================================
privateSnippetExecutor(void)403 extern "C" void privateSnippetExecutor( void )
404 {
405 asm volatile (
406 " .text\n"
407 " .align 2\n"
408 ".globl privateSnippetExecutor\n"
409 " subq $160, %rsp\n"
410 " movq %r10, -152(%rbp)\n" // Save (nVtableOffset << 32) + nFunctionIndex
411
412 " movq %rdi, -112(%rbp)\n" // Save GP registers
413 " movq %rsi, -104(%rbp)\n"
414 " movq %rdx, -96(%rbp)\n"
415 " movq %rcx, -88(%rbp)\n"
416 " movq %r8 , -80(%rbp)\n"
417 " movq %r9 , -72(%rbp)\n"
418
419 " movsd %xmm0, -64(%rbp)\n" // Save FP registers
420 " movsd %xmm1, -56(%rbp)\n"
421 " movsd %xmm2, -48(%rbp)\n"
422 " movsd %xmm3, -40(%rbp)\n"
423 " movsd %xmm4, -32(%rbp)\n"
424 " movsd %xmm5, -24(%rbp)\n"
425 " movsd %xmm6, -16(%rbp)\n"
426 " movsd %xmm7, -8(%rbp)\n"
427
428 " leaq -144(%rbp), %r9\n" // 6th param: sal_uInt64* pRegisterReturn
429 " leaq 16(%rbp), %r8\n" // 5rd param: void** ovrflw
430 " leaq -64(%rbp), %rcx\n" // 4th param: void** fpreg
431 " leaq -112(%rbp), %rdx\n" // 3rd param: void** gpreg
432 " movl -148(%rbp), %esi\n" // 2nd param: sal_int32 nVtableOffset
433 " movl -152(%rbp), %edi\n" // 1st param: sal_int32 nFunctionIndex
434
435 " call _cpp_vtable_call\n"
436
437 " cmp $10, %rax\n" // typelib_TypeClass_FLOAT
438 " je .Lfloat\n"
439 " cmp $11, %rax\n" // typelib_TypeClass_DOUBLE
440 " je .Lfloat\n"
441
442 " movq -144(%rbp), %rax\n" // Return value (int case)
443 " movq -136(%rbp), %rdx\n" // Return value (int case)
444 " movq -144(%rbp), %xmm0\n" // Return value (int case)
445 " movq -136(%rbp), %xmm1\n" // Return value (int case)
446 " jmp .Lfinish\n"
447 ".Lfloat:\n"
448 " movsd -144(%rbp), %xmm0\n" // Return value (float/double case)
449 ".Lfinish:\n"
450 " addq $160, %rsp\n"
451 );
452 }
453 const int codeSnippetSize = 24;
454
455 // Generate a trampoline that redirects method calls to
456 // privateSnippetExecutor().
457 //
458 // privateSnippetExecutor() saves all the registers that are used for
459 // parameter passing on x86_64, and calls the cpp_vtable_call().
460 // When it returns, privateSnippetExecutor() sets the return value.
461 //
462 // Note: The code snippet we build here must not create a stack frame,
463 // otherwise the UNO exceptions stop working thanks to non-existing
464 // unwinding info.
codeSnippet(unsigned char * code,sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,bool bHasHiddenParam)465 unsigned char * codeSnippet( unsigned char * code,
466 sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
467 bool bHasHiddenParam ) SAL_THROW( () )
468 {
469 sal_uInt64 nOffsetAndIndex = ( static_cast<sal_uInt64>( nVtableOffset ) << 32 ) | static_cast<sal_uInt64>( nFunctionIndex );
470
471 if ( bHasHiddenParam )
472 nOffsetAndIndex |= 0x80000000;
473
474 // movq $<nOffsetAndIndex>, %r10
475 *reinterpret_cast<sal_uInt16 *>( code ) = 0xba49;
476 *reinterpret_cast<sal_uInt64 *>( code + 2 ) = nOffsetAndIndex;
477
478 // movq $<address of the privateSnippetExecutor>, %r11
479 *reinterpret_cast<sal_uInt16 *>( code + 10 ) = 0xbb49;
480 *reinterpret_cast<sal_uInt64 *>( code + 12 ) = reinterpret_cast<sal_uInt64>( privateSnippetExecutor );
481
482 // jmpq *%r11
483 *reinterpret_cast<sal_uInt32 *>( code + 20 ) = 0x00e3ff49;
484
485 return code + codeSnippetSize;
486 }
487
488 //==================================================================================================
489 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
490
491 bridges::cpp_uno::shared::VtableFactory::Slot *
mapBlockToVtable(void * block)492 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
493 {
494 return static_cast< Slot * >(block) + 2;
495 }
496
497 //==================================================================================================
getBlockSize(sal_Int32 slotCount)498 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
499 sal_Int32 slotCount)
500 {
501 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
502 }
503
504 //==================================================================================================
505 bridges::cpp_uno::shared::VtableFactory::Slot *
initializeBlock(void * block,sal_Int32 slotCount)506 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
507 void * block, sal_Int32 slotCount)
508 {
509 Slot * slots = mapBlockToVtable(block);
510 slots[-2].fn = 0;
511 slots[-1].fn = 0;
512 return slots + slotCount;
513 }
514
515 //==================================================================================================
516
addLocalFunctions(Slot ** slots,unsigned char * code,typelib_InterfaceTypeDescription const * type,sal_Int32 nFunctionOffset,sal_Int32 functionCount,sal_Int32 nVtableOffset)517 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
518 Slot ** slots, unsigned char * code, /*sal_PtrDiff writetoexecdiff,*/
519 typelib_InterfaceTypeDescription const * type, sal_Int32 nFunctionOffset,
520 sal_Int32 functionCount, sal_Int32 nVtableOffset )
521 {
522 const sal_PtrDiff writetoexecdiff = 0;
523 (*slots) -= functionCount;
524 Slot * s = *slots;
525 for ( sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos )
526 {
527 typelib_TypeDescription * pTD = 0;
528
529 TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] );
530 OSL_ASSERT( pTD );
531
532 if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass )
533 {
534 typelib_InterfaceAttributeTypeDescription *pAttrTD =
535 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
536
537 // get method
538 (s++)->fn = code + writetoexecdiff;
539 code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
540 x86_64::return_in_hidden_param( pAttrTD->pAttributeTypeRef ) );
541
542 if ( ! pAttrTD->bReadOnly )
543 {
544 // set method
545 (s++)->fn = code + writetoexecdiff;
546 code = codeSnippet( code, nFunctionOffset++, nVtableOffset, false );
547 }
548 }
549 else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass )
550 {
551 typelib_InterfaceMethodTypeDescription *pMethodTD =
552 reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
553
554 (s++)->fn = code + writetoexecdiff;
555 code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
556 x86_64::return_in_hidden_param( pMethodTD->pReturnTypeRef ) );
557 }
558 else
559 OSL_ASSERT( false );
560
561 TYPELIB_DANGER_RELEASE( pTD );
562 }
563 return code;
564 }
565
566 //==================================================================================================
flushCode(unsigned char const *,unsigned char const *)567 void bridges::cpp_uno::shared::VtableFactory::flushCode(
568 unsigned char const *, unsigned char const * )
569 {
570 }
571