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