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 = 48; 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 // When it doubt about correctness, 373 // uncomment this and disassemble at runtime: 374 // INT 0x3 375 //*p++ = 0xcc; 376 377 if (isArgFloat[0]) 378 { 379 // movsd QWORD[rsp+8], XMM0 380 *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x44; *p++ = 0x24; *p++ = 0x08; 381 } 382 else 383 { 384 // mov QWORD[rsp+8], rcx 385 *p++ = 0x48; *p++ = 0x89; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x08; 386 } 387 388 if (isArgFloat[1]) 389 { 390 // movsd QWORD[rsp+16], XMM1 391 *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x10; 392 } 393 else 394 { 395 // mov QWORD[rsp+16], rdx 396 *p++ = 0x48; *p++ = 0x89; *p++ = 0x54; *p++ = 0x24; *p++ = 0x10; 397 } 398 399 if (isArgFloat[2]) 400 { 401 // movsd QWORD[rsp+24], XMM2 402 *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x54; *p++ = 0x24; *p++ = 0x18; 403 } 404 else 405 { 406 // mov QWORD[rsp+24], r8 407 *p++ = 0x4c; *p++ = 0x89; *p++ = 0x44; *p++ = 0x24; *p++ = 0x18; 408 } 409 410 if (isArgFloat[3]) 411 { 412 // movsd QWORD[rsp+32], XMM3 413 *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x5c; *p++ = 0x24; *p++ = 0x20; 414 } 415 else 416 { 417 // mov QWORD[rsp+32], r9 418 *p++ = 0x4c; *p++ = 0x89; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x20; 419 } 420 421 // mov rax, functionIndex 422 *p++ = 0xb8; 423 *p++ = functionIndex & 0xff; 424 *p++ = (functionIndex >> 8) & 0xff; 425 *p++ = (functionIndex >> 16) & 0xff; 426 *p++ = (functionIndex >> 24) & 0xff; 427 428 // mov r10, vtableOffset 429 *p++ = 0x41; 430 *p++ = 0xba; 431 *p++ = vtableOffset & 0xff; 432 *p++ = (vtableOffset >> 8) & 0xff; 433 *p++ = (vtableOffset >> 16) & 0xff; 434 *p++ = (vtableOffset >> 24) & 0xff; 435 436 // mov r11, privateSnippetExecutor 437 *p++ = 0x49; 438 *p++ = 0xbb; 439 *p++ = ((sal_uIntPtr)(&privateSnippetExecutor)) & 0xff; 440 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 8) & 0xff; 441 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 16) & 0xff; 442 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 24) & 0xff; 443 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 32) & 0xff; 444 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 40) & 0xff; 445 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 48) & 0xff; 446 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 56) & 0xff; 447 448 // jmp r11 449 *p++ = 0x41; 450 *p++ = 0xff; 451 *p++ = 0xe3; 452 453 OSL_ASSERT(p - code <= codeSnippetSize); 454 return code + codeSnippetSize; 455 } 456 457 } 458 459 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; 460 461 bridges::cpp_uno::shared::VtableFactory::Slot * 462 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) 463 { 464 return static_cast< Slot * >(block) + 1; 465 } 466 467 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( 468 sal_Int32 slotCount) 469 { 470 return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize; 471 } 472 473 bridges::cpp_uno::shared::VtableFactory::Slot * 474 bridges::cpp_uno::shared::VtableFactory::initializeBlock( 475 void * block, sal_Int32 slotCount) 476 { 477 struct RttiCompleteObjectLocator { 478 sal_uInt32 signature; 479 sal_uInt32 offset; // offset of vtable in objects of the class 480 sal_uInt32 cdOffset; // constructor displacement offset 481 // On AMD64, these 2 are offsets from the module's base address (when signature == 0): 482 sal_uInt32 typeDescriptorAddress; 483 sal_uInt32 classDescriptorAddress; 484 sal_uInt32 objectBase; // ignored when signature == 0 485 486 RttiCompleteObjectLocator(): signature(0), offset(0), cdOffset(0) 487 { 488 type_info *typeInfo = CPPU_CURRENT_NAMESPACE::mscx_getRTTI( 489 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 490 "com.sun.star.uno.XInterface"))); 491 HMODULE thisDLLBase; 492 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)&bridges::cpp_uno::shared::VtableFactory::initializeBlock, &thisDLLBase); 493 typeDescriptorAddress = (sal_uInt32) (((char*)typeInfo) - (char*)thisDLLBase); 494 classDescriptorAddress = 0; 495 objectBase = 0; 496 } 497 }; 498 static RttiCompleteObjectLocator rtti; 499 500 Slot * slots = mapBlockToVtable(block); 501 slots[-1].fn = &rtti; 502 return slots + slotCount; 503 } 504 505 static void findFirst4Win64ArgumentTypes( 506 typelib_MethodParameter *pParams, sal_Int32 nParams, 507 typelib_TypeDescriptionReference *pReturnType, bool isArgFloat[4]) 508 { 509 sal_uInt32 index = 0; 510 511 isArgFloat[0] = isArgFloat[1] = isArgFloat[2] = isArgFloat[3] = false; 512 513 // C++ "this" pointer: 514 ++index; 515 516 // https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2017 517 // "Otherwise the caller assumes the responsibility of allocating memory 518 // and passing a pointer for the return value as the first argument. 519 // Subsequent arguments are then shifted one argument to the right. 520 // The same pointer must be returned by the callee in RAX." 521 if ( pReturnType && x86_64::return_in_hidden_param( pReturnType ) ) 522 ++index; 523 524 for (int param = 0; param < nParams; param++) 525 { 526 if (index >= 4) 527 break; 528 529 typelib_TypeDescription *pParamTypeDescr = 0; 530 531 TYPELIB_DANGER_GET( &pParamTypeDescr, pParams[param].pTypeRef ); 532 OSL_ASSERT( pParamTypeDescr ); 533 534 isArgFloat[index++] = !pParams[param].bOut && 535 (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT || 536 pParamTypeDescr->eTypeClass == typelib_TypeClass_DOUBLE); 537 538 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 539 } 540 } 541 542 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( 543 Slot ** slots, unsigned char * code, 544 typelib_InterfaceTypeDescription const *type, sal_Int32 functionOffset, 545 sal_Int32 functionCount, sal_Int32 vtableOffset) 546 { 547 (*slots) -= functionCount; 548 Slot * s = *slots; 549 for (sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos) { 550 typelib_TypeDescription * pTD = 0; 551 552 TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] ); 553 OSL_ASSERT( pTD ); 554 555 bool isArgFloat[4]; 556 if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass ) 557 { 558 typelib_InterfaceAttributeTypeDescription *pAttrTD = 559 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD ); 560 561 // get method 562 findFirst4Win64ArgumentTypes(0, 0, pAttrTD->pAttributeTypeRef, isArgFloat); 563 (s++)->fn = code; 564 code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat); 565 566 if ( ! pAttrTD->bReadOnly ) 567 { 568 // set method 569 typelib_MethodParameter aParam; 570 aParam.pTypeRef = pAttrTD->pAttributeTypeRef; 571 aParam.bIn = sal_True; 572 aParam.bOut = sal_False; 573 findFirst4Win64ArgumentTypes(&aParam, 1, 0, isArgFloat); 574 (s++)->fn = code; 575 code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat); 576 } 577 } 578 else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass ) 579 { 580 typelib_InterfaceMethodTypeDescription *pMethodTD = 581 reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD ); 582 findFirst4Win64ArgumentTypes(pMethodTD->pParams, pMethodTD->nParams, 583 pMethodTD->pReturnTypeRef, isArgFloat); 584 (s++)->fn = code; 585 code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat); 586 } 587 else 588 OSL_ASSERT( false ); 589 590 TYPELIB_DANGER_RELEASE( pTD ); 591 } 592 return code; 593 } 594 595 void bridges::cpp_uno::shared::VtableFactory::flushCode( 596 unsigned char const *, unsigned char const *) 597 {} 598