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 <malloc.h> 28 29 #include <com/sun/star/uno/genfunc.hxx> 30 #include <uno/data.h> 31 #include <typelib/typedescription.hxx> 32 33 #include "bridges/cpp_uno/shared/bridge.hxx" 34 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" 35 #include "bridges/cpp_uno/shared/types.hxx" 36 #include "bridges/cpp_uno/shared/vtablefactory.hxx" 37 38 #include "abi.hxx" 39 #include "mscx.hxx" 40 41 using namespace ::rtl; 42 using namespace ::com::sun::star::uno; 43 44 namespace 45 { 46 47 //================================================================================================== 48 49 // Perform the UNO call 50 // 51 // We must convert the parameters stored in pCallStack to UNO 52 // arguments and call pThis->getUnoI()->pDispatcher. 53 // 54 // pCallStack: ret addr, this, [ret *], [params] 55 // 56 // [ret *] is present when we are returning a structure bigger than 8 bytes 57 // Simple types are returned in rax, or xmm0 (fp). 58 // Similarly structures <= 8 bytes are in rax, xmm0 as necessary. 59 static inline typelib_TypeClass cpp2uno_call( 60 bridges::cpp_uno::shared::CppInterfaceProxy * pThis, 61 const typelib_TypeDescription * pMemberTypeDescr, 62 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return 63 sal_Int32 nParams, typelib_MethodParameter * pParams, 64 void ** pCallStack, 65 sal_uInt64 * pRegisterReturn /* space for register return */ ) 66 { 67 // return 68 typelib_TypeDescription * pReturnTypeDescr = 0; 69 if (pReturnTypeRef) 70 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); 71 72 void * pUnoReturn = 0; 73 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need 74 75 if ( pReturnTypeDescr ) 76 { 77 if ( x86_64::return_in_hidden_param( pReturnTypeRef ) ) 78 { 79 // complex return via ptr (pCppReturn) 80 pCppReturn = pCallStack[2]; 81 ++pCallStack; 82 83 pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) 84 ? alloca( pReturnTypeDescr->nSize ) 85 : pCppReturn ); // direct way 86 } 87 else 88 pUnoReturn = pRegisterReturn; // direct way for simple types 89 } 90 91 // skip to first argument 92 pCallStack += 2; 93 94 // stack space 95 // parameters 96 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); 97 void ** pCppArgs = pUnoArgs + nParams; 98 // indices of values this have to be converted (interface conversion cpp<=>uno) 99 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); 100 // type descriptions for reconversions 101 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); 102 103 sal_Int32 nTempIndizes = 0; 104 105 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 106 { 107 const typelib_MethodParameter & rParam = pParams[nPos]; 108 typelib_TypeDescription * pParamTypeDescr = 0; 109 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); 110 111 if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) // value 112 { 113 pCppArgs[nPos] = pUnoArgs[nPos] = pCallStack++; 114 // no longer needed 115 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 116 } 117 else // ptr to complex value || ref 118 { 119 void *pCppStack; 120 pCppArgs[nPos] = pCppStack = *pCallStack++; 121 122 if (! rParam.bIn) // is pure out 123 { 124 // uno out is unconstructed mem! 125 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); 126 pTempIndizes[nTempIndizes] = nPos; 127 // will be released at reconversion 128 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 129 } 130 else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ) ) // is in/inout 131 { 132 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), 133 pCppStack, pParamTypeDescr, 134 pThis->getBridge()->getCpp2Uno() ); 135 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted 136 // will be released at reconversion 137 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 138 } 139 else // direct way 140 { 141 pUnoArgs[nPos] = pCppStack; 142 // no longer needed 143 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 144 } 145 } 146 } 147 148 // ExceptionHolder 149 uno_Any aUnoExc; // Any will be constructed by callee 150 uno_Any * pUnoExc = &aUnoExc; 151 152 // invoke uno dispatch call 153 (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); 154 155 // in case an exception occurred... 156 if ( pUnoExc ) 157 { 158 // destruct temporary in/inout params 159 for ( ; nTempIndizes--; ) 160 { 161 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 162 163 if (pParams[nIndex].bIn) // is in/inout => was constructed 164 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); 165 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); 166 } 167 if (pReturnTypeDescr) 168 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 169 170 CPPU_CURRENT_NAMESPACE::mscx_raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any 171 // is here for dummy 172 return typelib_TypeClass_VOID; 173 } 174 else // else no exception occurred... 175 { 176 // temporary params 177 for ( ; nTempIndizes--; ) 178 { 179 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 180 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; 181 182 if ( pParams[nIndex].bOut ) // inout/out 183 { 184 // convert and assign 185 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); 186 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, 187 pThis->getBridge()->getUno2Cpp() ); 188 } 189 // destroy temp uno param 190 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); 191 192 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 193 } 194 // return 195 if ( pCppReturn ) // has complex return 196 { 197 if ( pUnoReturn != pCppReturn ) // needs reconversion 198 { 199 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, 200 pThis->getBridge()->getUno2Cpp() ); 201 // destroy temp uno return 202 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); 203 } 204 // complex return ptr is set to rax 205 *(void **)pRegisterReturn = pCppReturn; 206 } 207 if ( pReturnTypeDescr ) 208 { 209 typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; 210 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 211 return eRet; 212 } 213 else 214 return typelib_TypeClass_VOID; 215 } 216 } 217 218 219 //================================================================================================== 220 extern "C" typelib_TypeClass cpp_vtable_call( 221 void ** pCallStack, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, 222 sal_uInt64 * pRegisterReturn /* space for register return */ ) 223 { 224 // pCallStack: ret adr, this, [ret *], params 225 void * pThis = static_cast< char * >(pCallStack[1]) - nVtableOffset; 226 227 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI = 228 bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis ); 229 230 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); 231 232 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); 233 if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex ) 234 { 235 throw RuntimeException( OUString::createFromAscii("illegal vtable index!"), 236 reinterpret_cast<XInterface *>( pCppI ) ); 237 } 238 239 // determine called method 240 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; 241 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); 242 243 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); 244 245 typelib_TypeClass eRet; 246 switch ( aMemberDescr.get()->eTypeClass ) 247 { 248 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 249 { 250 typelib_TypeDescriptionReference *pAttrTypeRef = 251 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef; 252 253 if ( pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex ) 254 { 255 // is GET method 256 eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef, 257 0, 0, // no params 258 pCallStack, pRegisterReturn ); 259 } 260 else 261 { 262 // is SET method 263 typelib_MethodParameter aParam; 264 aParam.pTypeRef = pAttrTypeRef; 265 aParam.bIn = sal_True; 266 aParam.bOut = sal_False; 267 268 eRet = cpp2uno_call( pCppI, aMemberDescr.get(), 269 0, // indicates void return 270 1, &aParam, 271 pCallStack, pRegisterReturn ); 272 } 273 break; 274 } 275 case typelib_TypeClass_INTERFACE_METHOD: 276 { 277 // is METHOD 278 switch ( nFunctionIndex ) 279 { 280 // standard XInterface vtable calls 281 case 1: // acquire() 282 pCppI->acquireProxy(); // non virtual call! 283 eRet = typelib_TypeClass_VOID; 284 break; 285 case 2: // release() 286 pCppI->releaseProxy(); // non virtual call! 287 eRet = typelib_TypeClass_VOID; 288 break; 289 case 0: // queryInterface() opt 290 { 291 typelib_TypeDescription * pTD = 0; 292 TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( pCallStack[3] )->getTypeLibType() ); 293 if ( pTD ) 294 { 295 XInterface * pInterface = 0; 296 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface) 297 ( pCppI->getBridge()->getCppEnv(), 298 (void **)&pInterface, 299 pCppI->getOid().pData, 300 reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) ); 301 302 if ( pInterface ) 303 { 304 ::uno_any_construct( reinterpret_cast<uno_Any *>( pCallStack[1] ), 305 &pInterface, pTD, cpp_acquire ); 306 307 pInterface->release(); 308 TYPELIB_DANGER_RELEASE( pTD ); 309 310 reinterpret_cast<void **>( pRegisterReturn )[0] = pCallStack[1]; 311 eRet = typelib_TypeClass_ANY; 312 break; 313 } 314 TYPELIB_DANGER_RELEASE( pTD ); 315 } 316 } // else perform queryInterface() 317 default: 318 { 319 typelib_InterfaceMethodTypeDescription *pMethodTD = 320 reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() ); 321 322 eRet = cpp2uno_call( pCppI, aMemberDescr.get(), 323 pMethodTD->pReturnTypeRef, 324 pMethodTD->nParams, 325 pMethodTD->pParams, 326 pCallStack, pRegisterReturn ); 327 } 328 } 329 break; 330 } 331 default: 332 { 333 throw RuntimeException( OUString::createFromAscii("no member description found!"), 334 reinterpret_cast<XInterface *>( pCppI ) ); 335 // is here for dummy 336 eRet = typelib_TypeClass_VOID; 337 } 338 } 339 340 return eRet; 341 } 342 343 //================================================================================================== 344 extern "C" void privateSnippetExecutor( ... ); 345 346 int const codeSnippetSize = 44; 347 348 unsigned char * codeSnippet( 349 unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, bool isArgFloat[4]) 350 { 351 unsigned char * p = code; 352 353 354 // 355 // | ... | 356 // +----------------------------+ 357 // | argument 4 | 358 // rsp+40 +----------------------------+ ------- 359 // | argument 3, r9/xmm3 home | ^ shadow 360 // rsp+32 +----------------------------+ | space, 361 // | argument 2, r8/xmm2 home | | guaranteed to be present but uninitialized, 362 // rsp+24 +----------------------------+ | we have to copy 363 // | argument 1, rdx/xmm1 home | | the first 4 parameters there from the registers, 364 // rsp+16 +----------------------------+ | to form the continuous array of arguments. 365 // | argument 0, rcx/xmm0 home | v 366 // rsp+08 +----------------------------+ ------- 367 // | return address | 368 // rsp--> +----------------------------+ 369 // 370 // 371 372 if (isArgFloat[0]) 373 { 374 // movsd QWORD[rsp+8], XMM0 375 *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x44; *p++ = 0x24; *p++ = 0x08; 376 } 377 else 378 { 379 // mov QWORD[rsp+8], rcx 380 *p++ = 0x48; *p++ = 0x49; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x08; 381 } 382 383 if (isArgFloat[1]) 384 { 385 // movsd QWORD[rsp+16], XMM1 386 *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x10; 387 } 388 else 389 { 390 // mov QWORD[rsp+16], rdx 391 *p++ = 0x48; *p++ = 0x49; *p++ = 0x54; *p++ = 0x24; *p++ = 0x10; 392 } 393 394 if (isArgFloat[2]) 395 { 396 // movsd QWORD[rsp+24], XMM2 397 *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x54; *p++ = 0x24; *p++ = 0x18; 398 } 399 else 400 { 401 // mov QWORD[rsp+24], r8 402 *p++ = 0x4c; *p++ = 0x89; *p++ = 0x44; *p++ = 0x24; *p++ = 0x18; 403 } 404 405 if (isArgFloat[3]) 406 { 407 // movsd QWORD[rsp+32], XMM3 408 *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x5c; *p++ = 0x24; *p++ = 0x20; 409 } 410 else 411 { 412 // mov QWORD[rsp+32], r9 413 *p++ = 0x4c; *p++ = 0x89; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x20; 414 } 415 416 // mov rax, functionIndex 417 *p++ = 0xb8; 418 *p++ = functionIndex & 0xff; 419 *p++ = (functionIndex >> 8) & 0xff; 420 *p++ = (functionIndex >> 16) & 0xff; 421 *p++ = (functionIndex >> 24) & 0xff; 422 423 // mov r10, vtableOffset 424 *p++ = 0x41; 425 *p++ = 0xba; 426 *p++ = vtableOffset & 0xff; 427 *p++ = (vtableOffset >> 8) & 0xff; 428 *p++ = (vtableOffset >> 16) & 0xff; 429 *p++ = (vtableOffset >> 24) & 0xff; 430 431 // mov r11, privateSnippetExecutor 432 *p++ = 0x49; 433 *p++ = 0xbb; 434 *p++ = ((sal_uIntPtr)(&privateSnippetExecutor)) & 0xff; 435 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 8) & 0xff; 436 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 16) & 0xff; 437 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 24) & 0xff; 438 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 32) & 0xff; 439 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 40) & 0xff; 440 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 48) & 0xff; 441 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 56) & 0xff; 442 443 // jmp r11 444 *p++ = 0x49; 445 *p++ = 0xff; 446 *p++ = 0xe3; 447 448 OSL_ASSERT(p - code <= codeSnippetSize); 449 return code + codeSnippetSize; 450 } 451 452 } 453 454 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; 455 456 bridges::cpp_uno::shared::VtableFactory::Slot * 457 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) 458 { 459 return static_cast< Slot * >(block) + 1; 460 } 461 462 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( 463 sal_Int32 slotCount) 464 { 465 return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize; 466 } 467 468 bridges::cpp_uno::shared::VtableFactory::Slot * 469 bridges::cpp_uno::shared::VtableFactory::initializeBlock( 470 void * block, sal_Int32 slotCount) 471 { 472 struct RttiCompleteObjectLocator { 473 sal_uInt32 signature; 474 sal_uInt32 offset; // offset of vtable in objects of the class 475 sal_uInt32 cdOffset; // constructor displacement offset 476 // On AMD64, these 2 are offsets from the module's base address (when signature == 0): 477 sal_uInt32 typeDescriptorAddress; 478 sal_uInt32 classDescriptorAddress; 479 sal_uInt32 objectBase; // ignored when signature == 0 480 481 RttiCompleteObjectLocator(): signature(0), offset(0), cdOffset(0) 482 { 483 type_info *typeInfo = CPPU_CURRENT_NAMESPACE::mscx_getRTTI( 484 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 485 "com.sun.star.uno.XInterface"))); 486 HMODULE thisDLLBase; 487 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)&bridges::cpp_uno::shared::VtableFactory::initializeBlock, &thisDLLBase); 488 typeDescriptorAddress = (sal_uInt32) (((char*)typeInfo) - (char*)thisDLLBase); 489 classDescriptorAddress = 0; 490 objectBase = 0; 491 } 492 }; 493 static RttiCompleteObjectLocator rtti; 494 495 Slot * slots = mapBlockToVtable(block); 496 slots[-1].fn = &rtti; 497 return slots + slotCount; 498 } 499 500 static void findFirst4Win64ArgumentTypes( 501 typelib_MethodParameter *pParams, sal_Int32 nParams, 502 typelib_TypeDescriptionReference *pReturnType, bool isArgFloat[4]) 503 { 504 sal_uInt32 index = 0; 505 506 isArgFloat[0] = isArgFloat[1] = isArgFloat[2] = isArgFloat[3] = false; 507 508 // C++ "this" pointer: 509 ++index; 510 511 // https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2017 512 // "Otherwise the caller assumes the responsibility of allocating memory 513 // and passing a pointer for the return value as the first argument. 514 // Subsequent arguments are then shifted one argument to the right. 515 // The same pointer must be returned by the callee in RAX." 516 if ( pReturnType && x86_64::return_in_hidden_param( pReturnType ) ) 517 ++index; 518 519 for (int param = 0; param < nParams; param++) 520 { 521 if (index >= 4) 522 break; 523 524 typelib_TypeDescription *pParamTypeDescr = 0; 525 526 TYPELIB_DANGER_GET( &pParamTypeDescr, pParams[param].pTypeRef ); 527 OSL_ASSERT( pParamTypeDescr ); 528 529 isArgFloat[index++] = !pParams[param].bOut && 530 (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT || 531 pParamTypeDescr->eTypeClass == typelib_TypeClass_DOUBLE); 532 533 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 534 } 535 } 536 537 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( 538 Slot ** slots, unsigned char * code, 539 typelib_InterfaceTypeDescription const *type, sal_Int32 functionOffset, 540 sal_Int32 functionCount, sal_Int32 vtableOffset) 541 { 542 (*slots) -= functionCount; 543 Slot * s = *slots; 544 for (sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos) { 545 typelib_TypeDescription * pTD = 0; 546 547 TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] ); 548 OSL_ASSERT( pTD ); 549 550 bool isArgFloat[4]; 551 if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass ) 552 { 553 typelib_InterfaceAttributeTypeDescription *pAttrTD = 554 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD ); 555 556 // get method 557 findFirst4Win64ArgumentTypes(0, 0, pAttrTD->pAttributeTypeRef, isArgFloat); 558 (s++)->fn = code; 559 code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat); 560 561 if ( ! pAttrTD->bReadOnly ) 562 { 563 // set method 564 typelib_MethodParameter aParam; 565 aParam.pTypeRef = pAttrTD->pAttributeTypeRef; 566 aParam.bIn = sal_True; 567 aParam.bOut = sal_False; 568 findFirst4Win64ArgumentTypes(&aParam, 1, 0, isArgFloat); 569 (s++)->fn = code; 570 code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat); 571 } 572 } 573 else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass ) 574 { 575 typelib_InterfaceMethodTypeDescription *pMethodTD = 576 reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD ); 577 findFirst4Win64ArgumentTypes(pMethodTD->pParams, pMethodTD->nParams, 578 pMethodTD->pReturnTypeRef, isArgFloat); 579 (s++)->fn = code; 580 code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat); 581 } 582 else 583 OSL_ASSERT( false ); 584 585 TYPELIB_DANGER_RELEASE( pTD ); 586 } 587 return code; 588 } 589 590 void bridges::cpp_uno::shared::VtableFactory::flushCode( 591 unsigned char const *, unsigned char const *) 592 {} 593