1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_bridges.hxx" 30 31 #include <com/sun/star/uno/genfunc.hxx> 32 #include <uno/data.h> 33 #include <typelib/typedescription.hxx> 34 35 #include "bridges/cpp_uno/shared/bridge.hxx" 36 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" 37 #include "bridges/cpp_uno/shared/types.hxx" 38 #include "bridges/cpp_uno/shared/vtablefactory.hxx" 39 40 #include "share.hxx" 41 42 using namespace ::com::sun::star::uno; 43 44 namespace 45 { 46 47 //================================================================================================== 48 static typelib_TypeClass cpp2uno_call( 49 bridges::cpp_uno::shared::CppInterfaceProxy * pThis, 50 const typelib_TypeDescription * pMemberTypeDescr, 51 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return 52 sal_Int32 nParams, typelib_MethodParameter * pParams, 53 void ** gpreg, void ** fpreg, void ** ovrflw, 54 sal_Int64 * pRegisterReturn /* space for register return */ ) 55 { 56 57 // gpreg: [ret *], this, [gpr params] 58 // fpreg: [fpr params] 59 // ovrflw: [gpr or fpr params (space for entire parameter list in structure format properly aligned)] 60 61 // return 62 typelib_TypeDescription * pReturnTypeDescr = 0; 63 if (pReturnTypeRef) 64 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); 65 66 void * pUnoReturn = 0; 67 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need 68 69 sal_Int32 ngpreg = 0; 70 sal_Int32 nfpreg = 0; 71 72 73 if (pReturnTypeDescr) 74 { 75 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) 76 pUnoReturn = pRegisterReturn; // direct way for simple types 77 else // complex return via ptr (pCppReturn) 78 { 79 pCppReturn = *gpreg; 80 ngpreg++; 81 ++ovrflw; 82 83 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) 84 ? alloca( pReturnTypeDescr->nSize ) 85 : pCppReturn); // direct way 86 } 87 } 88 // pop this 89 ngpreg++; 90 ++ovrflw; 91 92 // after handling optional return pointer and "this" 93 // make use of the space that is allocated to store all parameters in the callers stack 94 // by comying the proper registers filled with parameters to that space 95 char * pCppStack = (char *)ovrflw; 96 97 98 sal_Int32 nPos; 99 100 for ( nPos = 0; nPos < nParams; ++nPos ) 101 { 102 const typelib_MethodParameter & rParam = pParams[nPos]; 103 if (rParam.bOut) 104 { 105 if (ngpreg < 8) 106 { 107 *(sal_Int32 *)pCppStack = ((sal_Int32 *)gpreg)[ngpreg++]; 108 } 109 pCppStack += sizeof (sal_Int32); 110 } 111 else 112 { 113 switch (rParam.pTypeRef->eTypeClass) 114 { 115 case typelib_TypeClass_FLOAT: 116 if (nfpreg < 13) 117 { 118 *(float *)pCppStack = ((double *)fpreg)[nfpreg++]; 119 } 120 pCppStack += sizeof (float); 121 ngpreg += 1; 122 break; 123 case typelib_TypeClass_DOUBLE: 124 if (nfpreg < 13) 125 { 126 *(double *)pCppStack = ((double *)fpreg)[nfpreg++]; 127 } 128 pCppStack += sizeof (double); 129 ngpreg += 2; 130 break; 131 case typelib_TypeClass_UNSIGNED_HYPER: 132 case typelib_TypeClass_HYPER: 133 if (ngpreg < 8) 134 { 135 *(sal_Int32 *)pCppStack = ((sal_Int32 *)gpreg)[ngpreg++]; 136 } 137 pCppStack += sizeof (sal_Int32); 138 // fall through on purpose 139 default: 140 if (ngpreg < 8) 141 { 142 *(sal_Int32 *)pCppStack = ((sal_Int32 *)gpreg)[ngpreg++]; 143 } 144 pCppStack += sizeof (sal_Int32); 145 } 146 } 147 } 148 149 // now the stack has all of the paramters stored in it ready to be processed 150 // so we are ready to build the uno call stack 151 pCppStack = (char *)ovrflw; 152 153 // stack space 154 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); 155 156 // parameters 157 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); 158 void ** pCppArgs = pUnoArgs + nParams; 159 160 // indizes of values this have to be converted (interface conversion cpp<=>uno) 161 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); 162 163 // type descriptions for reconversions 164 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); 165 166 sal_Int32 nTempIndizes = 0; 167 168 for ( nPos = 0; nPos < nParams; ++nPos ) 169 { 170 const typelib_MethodParameter & rParam = pParams[nPos]; 171 typelib_TypeDescription * pParamTypeDescr = 0; 172 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); 173 174 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) 175 // value 176 { 177 switch (pParamTypeDescr->eTypeClass) 178 { 179 case typelib_TypeClass_BOOLEAN: 180 case typelib_TypeClass_BYTE: 181 pCppArgs[nPos] = pCppStack +3; 182 pUnoArgs[nPos] = pCppStack +3; 183 break; 184 case typelib_TypeClass_CHAR: 185 case typelib_TypeClass_SHORT: 186 case typelib_TypeClass_UNSIGNED_SHORT: 187 pCppArgs[nPos] = pCppStack +2; 188 pUnoArgs[nPos] = pCppStack +2; 189 break; 190 case typelib_TypeClass_HYPER: 191 case typelib_TypeClass_UNSIGNED_HYPER: 192 case typelib_TypeClass_DOUBLE: 193 pCppArgs[nPos] = pCppStack; 194 pUnoArgs[nPos] = pCppStack; 195 pCppStack += sizeof(sal_Int32); // extra long (two regs) 196 break; 197 default: 198 pCppArgs[nPos] = pCppStack; 199 pUnoArgs[nPos] = pCppStack; 200 } 201 // no longer needed 202 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 203 } 204 else // ptr to complex value | ref 205 { 206 pCppArgs[nPos] = *(void **)pCppStack; 207 208 if (! rParam.bIn) // is pure out 209 { 210 // uno out is unconstructed mem! 211 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); 212 pTempIndizes[nTempIndizes] = nPos; 213 // will be released at reconversion 214 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 215 } 216 // is in/inout 217 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) 218 { 219 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), 220 *(void **)pCppStack, pParamTypeDescr, 221 pThis->getBridge()->getCpp2Uno() ); 222 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted 223 // will be released at reconversion 224 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 225 } 226 else // direct way 227 { 228 pUnoArgs[nPos] = *(void **)pCppStack; 229 // no longer needed 230 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 231 } 232 } 233 pCppStack += sizeof(sal_Int32); // standard parameter length 234 } 235 236 237 // ExceptionHolder 238 uno_Any aUnoExc; // Any will be constructed by callee 239 uno_Any * pUnoExc = &aUnoExc; 240 241 // invoke uno dispatch call 242 (*pThis->getUnoI()->pDispatcher)( 243 pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); 244 245 // in case an exception occured... 246 if (pUnoExc) 247 { 248 // destruct temporary in/inout params 249 for ( ; nTempIndizes--; ) 250 { 251 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 252 253 if (pParams[nIndex].bIn) // is in/inout => was constructed 254 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); 255 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); 256 } 257 if (pReturnTypeDescr) 258 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 259 260 CPPU_CURRENT_NAMESPACE::raiseException( 261 &aUnoExc, pThis->getBridge()->getUno2Cpp() ); 262 // has to destruct the any 263 // is here for dummy 264 return typelib_TypeClass_VOID; 265 } 266 else // else no exception occured... 267 { 268 // temporary params 269 for ( ; nTempIndizes--; ) 270 { 271 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 272 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; 273 274 if (pParams[nIndex].bOut) // inout/out 275 { 276 // convert and assign 277 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); 278 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, 279 pThis->getBridge()->getUno2Cpp() ); 280 } 281 // destroy temp uno param 282 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); 283 284 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 285 } 286 // return 287 if (pCppReturn) // has complex return 288 { 289 if (pUnoReturn != pCppReturn) // needs reconversion 290 { 291 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, 292 pThis->getBridge()->getUno2Cpp() ); 293 // destroy temp uno return 294 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); 295 } 296 // complex return ptr is set to return reg 297 *(void **)pRegisterReturn = pCppReturn; 298 } 299 if (pReturnTypeDescr) 300 { 301 typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; 302 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 303 return eRet; 304 } 305 else 306 return typelib_TypeClass_VOID; 307 } 308 } 309 310 311 //================================================================================================== 312 static typelib_TypeClass cpp_mediate( 313 sal_Int32 nFunctionIndex, 314 sal_Int32 nVtableOffset, 315 void ** gpreg, void ** fpreg, void ** ovrflw, 316 sal_Int64 * pRegisterReturn /* space for register return */ ) 317 { 318 OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); 319 320 // gpreg: [ret *], this, [other gpr params] 321 // fpreg: [fpr params] 322 // ovrflw: [gpr or fpr params (in space allocated for all params properly aligned)] 323 324 void * pThis; 325 if( nFunctionIndex & 0x80000000 ) 326 { 327 nFunctionIndex &= 0x7fffffff; 328 pThis = gpreg[1]; 329 } 330 else 331 { 332 pThis = gpreg[0]; 333 } 334 335 pThis = static_cast< char * >(pThis) - nVtableOffset; 336 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI 337 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(pThis); 338 339 340 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); 341 342 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); 343 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) 344 { 345 throw RuntimeException( 346 rtl::OUString::createFromAscii("illegal vtable index!"), 347 (XInterface *)pThis ); 348 } 349 350 // determine called method 351 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; 352 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); 353 354 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); 355 356 typelib_TypeClass eRet; 357 switch (aMemberDescr.get()->eTypeClass) 358 { 359 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 360 { 361 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) 362 { 363 // is GET method 364 eRet = cpp2uno_call( 365 pCppI, aMemberDescr.get(), 366 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, 367 0, 0, // no params 368 gpreg, fpreg, ovrflw, pRegisterReturn ); 369 } 370 else 371 { 372 // is SET method 373 typelib_MethodParameter aParam; 374 aParam.pTypeRef = 375 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; 376 aParam.bIn = sal_True; 377 aParam.bOut = sal_False; 378 379 eRet = cpp2uno_call( 380 pCppI, aMemberDescr.get(), 381 0, // indicates void return 382 1, &aParam, 383 gpreg, fpreg, ovrflw, pRegisterReturn ); 384 } 385 break; 386 } 387 case typelib_TypeClass_INTERFACE_METHOD: 388 { 389 // is METHOD 390 switch (nFunctionIndex) 391 { 392 case 1: // acquire() 393 pCppI->acquireProxy(); // non virtual call! 394 eRet = typelib_TypeClass_VOID; 395 break; 396 case 2: // release() 397 pCppI->releaseProxy(); // non virtual call! 398 eRet = typelib_TypeClass_VOID; 399 break; 400 case 0: // queryInterface() opt 401 { 402 typelib_TypeDescription * pTD = 0; 403 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() ); 404 if (pTD) 405 { 406 XInterface * pInterface = 0; 407 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( 408 pCppI->getBridge()->getCppEnv(), 409 (void **)&pInterface, pCppI->getOid().pData, (typelib_InterfaceTypeDescription *)pTD ); 410 411 if (pInterface) 412 { 413 ::uno_any_construct( 414 reinterpret_cast< uno_Any * >( gpreg[0] ), 415 &pInterface, pTD, cpp_acquire ); 416 pInterface->release(); 417 TYPELIB_DANGER_RELEASE( pTD ); 418 *(void **)pRegisterReturn = gpreg[0]; 419 eRet = typelib_TypeClass_ANY; 420 break; 421 } 422 TYPELIB_DANGER_RELEASE( pTD ); 423 } 424 } // else perform queryInterface() 425 default: 426 eRet = cpp2uno_call( 427 pCppI, aMemberDescr.get(), 428 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, 429 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, 430 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, 431 gpreg, fpreg, ovrflw, pRegisterReturn ); 432 } 433 break; 434 } 435 default: 436 { 437 throw RuntimeException( 438 rtl::OUString::createFromAscii("no member description found!"), 439 (XInterface *)pThis ); 440 // is here for dummy 441 eRet = typelib_TypeClass_VOID; 442 } 443 } 444 445 return eRet; 446 } 447 448 //================================================================================================== 449 /** 450 * is called on incoming vtable calls 451 * (called by asm snippets) 452 */ 453 static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** fpregptr, void** ovrflw) 454 { 455 sal_Int32 gpreg[8]; 456 double fpreg[13]; 457 458 // FIXME: why are we restoring the volatile ctr register here 459 sal_Int32 ctrsave = ((sal_Int32*)gpregptr)[-1]; 460 461 memcpy( gpreg, gpregptr, 32); 462 memcpy( fpreg, fpregptr, 104); 463 464 volatile long nRegReturn[2]; 465 466 // sal_Bool bComplex = nFunctionIndex & 0x80000000 ? sal_True : sal_False; 467 468 typelib_TypeClass aType = 469 cpp_mediate( nFunctionIndex, nVtableOffset, (void**)gpreg, (void**)fpreg, ovrflw, (sal_Int64*)nRegReturn ); 470 471 // FIXME: why are we restoring the volatile ctr register here 472 // FIXME: and why are we putting back the values for r4, r5, and r6 as well 473 // FIXME: this makes no sense to me, all of these registers are volatile! 474 __asm__( "lwz r4, %0\n\t" 475 "mtctr r4\n\t" 476 "lwz r4, %1\n\t" 477 "lwz r5, %2\n\t" 478 "lwz r6, %3\n\t" 479 : : "m"(ctrsave), "m"(gpreg[1]), "m"(gpreg[2]), "m"(gpreg[3]) ); 480 481 switch( aType ) 482 { 483 484 // move return value into register space 485 // (will be loaded by machine code snippet) 486 487 case typelib_TypeClass_BOOLEAN: 488 case typelib_TypeClass_BYTE: 489 __asm__( "lbz r3,%0\n\t" : : 490 "m"(nRegReturn[0]) ); 491 break; 492 493 case typelib_TypeClass_CHAR: 494 case typelib_TypeClass_SHORT: 495 case typelib_TypeClass_UNSIGNED_SHORT: 496 __asm__( "lhz r3,%0\n\t" : : 497 "m"(nRegReturn[0]) ); 498 break; 499 500 case typelib_TypeClass_FLOAT: 501 __asm__( "lfs f1,%0\n\t" : : 502 "m" (*((float*)nRegReturn)) ); 503 break; 504 505 case typelib_TypeClass_DOUBLE: 506 __asm__( "lfd f1,%0\n\t" : : 507 "m" (*((double*)nRegReturn)) ); 508 break; 509 510 case typelib_TypeClass_HYPER: 511 case typelib_TypeClass_UNSIGNED_HYPER: 512 __asm__( "lwz r4,%0\n\t" : : 513 "m"(nRegReturn[1]) ); // fall through 514 515 default: 516 __asm__( "lwz r3,%0\n\t" : : 517 "m"(nRegReturn[0]) ); 518 break; 519 } 520 } 521 522 523 int const codeSnippetSize = 136; 524 525 unsigned char * codeSnippet( unsigned char * code, sal_Int32 functionIndex, 526 sal_Int32 vtableOffset, bool simpleRetType ) 527 { 528 if (! simpleRetType ) 529 functionIndex |= 0x80000000; 530 531 // OSL_ASSERT( sizeof (long) == 4 ); 532 533 // FIXME: why are we leaving an 8k gap in the stack here 534 // FIXME: is this to allow room for signal handling frames? 535 // FIXME: seems like overkill here but this is what was done for Mac OSX for gcc2 536 // FIXME: also why no saving of the non-volatile CR pieces here, to be safe 537 // FIXME: we probably should 538 539 /* generate this code */ 540 541 // # so first save gpr 3 to gpr 10 (aligned to 4) 542 // stw r3, -8000(r1) 543 // stw r4, -7996(r1) 544 // stw r5, -7992(r1) 545 // stw r6, -7988(r1) 546 // stw r7, -7984(r1) 547 // stw r8, -7980(r1) 548 // stw r9, -7976(r1) 549 // stw r10,-7972(r1) 550 551 // # next save fpr 1 to fpr 13 (aligned to 8) 552 // stfd f1, -7968(r1) 553 // stfd f2, -7960(r1) 554 // stfd f3, -7952(r1) 555 // stfd f4, -7944(r1) 556 // stfd f5, -7936(r1) 557 // stfd f6, -7928(r1) 558 // stfd f7, -7920(r1) 559 // stfd f8, -7912(r1) 560 // stfd f9, -7904(r1) 561 // stfd f10,-7896(r1) 562 // stfd f11,-7888(r1) 563 // stfd f12,-7880(r1) 564 // stfd f13,-7872(r1) 565 566 // FIXME: ctr is volatile, while are we saving it and not CR? 567 // mfctr r3 568 // stw r3, -8004(r1) 569 570 // # now here is where cpp_vtable_call must go 571 // lis r3,0xdead 572 // ori r3,r3,0xbeef 573 // mtctr r3 574 575 // # now load up the functionIndex number 576 // lis r3, 0xdead 577 // ori r3,r3,0xbeef 578 579 // # now load up the vtableOffset 580 // lis r4, 0xdead 581 // ori r4,r4,0xbeef 582 583 // #now load up the pointer to the saved gpr registers 584 // addi r5,r1,-8000 585 586 // #now load up the pointer to the saved fpr registers 587 // addi r6,r1,-7968 588 589 // #now load up the pointer to the overflow call stack 590 // addi r7,r1,24 # frame pointer plus 24 591 592 // bctr 593 594 unsigned long * p = (unsigned long *) code; 595 596 * p++ = 0x9061e0c0; 597 * p++ = 0x9081e0c4; 598 * p++ = 0x90a1e0c8; 599 * p++ = 0x90c1e0cc; 600 * p++ = 0x90e1e0d0; 601 * p++ = 0x9101e0d4; 602 * p++ = 0x9121e0d8; 603 * p++ = 0x9141e0dc; 604 * p++ = 0xd821e0e0; 605 * p++ = 0xd841e0e8; 606 * p++ = 0xd861e0f0; 607 * p++ = 0xd881e0f8; 608 * p++ = 0xd8a1e100; 609 * p++ = 0xd8c1e108; 610 * p++ = 0xd8e1e110; 611 * p++ = 0xd901e118; 612 * p++ = 0xd921e120; 613 * p++ = 0xd941e128; 614 * p++ = 0xd961e130; 615 * p++ = 0xd981e138; 616 * p++ = 0xd9a1e140; 617 * p++ = 0x7c6902a6; 618 * p++ = 0x9061e0bc; 619 * p++ = 0x3c600000 | (((unsigned long)cpp_vtable_call) >> 16); 620 * p++ = 0x60630000 | (((unsigned long)cpp_vtable_call) & 0x0000FFFF); 621 * p++ = 0x7c6903a6; 622 * p++ = 0x3c600000 | (((unsigned long)functionIndex) >> 16); 623 * p++ = 0x60630000 | (((unsigned long)functionIndex) & 0x0000FFFF); 624 * p++ = 0x3c800000 | (((unsigned long)vtableOffset) >> 16); 625 * p++ = 0x60840000 | (((unsigned long)vtableOffset) & 0x0000FFFF); 626 * p++ = 0x38a1e0c0; 627 * p++ = 0x38c1e0e0; 628 * p++ = 0x38e10018; 629 * p++ = 0x4e800420; 630 631 return (code + codeSnippetSize); 632 633 } 634 635 636 } 637 638 void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * bptr, unsigned char const * eptr) 639 { 640 int const lineSize = 32; 641 for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) { 642 __asm__ volatile ("dcbst 0, %0" : : "r"(p) : "memory"); 643 } 644 __asm__ volatile ("sync" : : : "memory"); 645 for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) { 646 __asm__ volatile ("icbi 0, %0" : : "r"(p) : "memory"); 647 } 648 __asm__ volatile ("isync" : : : "memory"); 649 } 650 651 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; 652 653 bridges::cpp_uno::shared::VtableFactory::Slot * 654 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) 655 { 656 return static_cast< Slot * >(block) + 2; 657 } 658 659 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( 660 sal_Int32 slotCount) 661 { 662 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; 663 } 664 665 bridges::cpp_uno::shared::VtableFactory::Slot * 666 bridges::cpp_uno::shared::VtableFactory::initializeBlock( 667 void * block, sal_Int32 slotCount) 668 { 669 Slot * slots = mapBlockToVtable(block); 670 slots[-2].fn = 0; 671 slots[-1].fn = 0; 672 return slots + slotCount; 673 } 674 675 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( 676 Slot ** slots, unsigned char * code, 677 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, 678 sal_Int32 functionCount, sal_Int32 vtableOffset) 679 { 680 (*slots) -= functionCount; 681 Slot * s = *slots; 682 683 // fprintf(stderr, "in addLocalFunctions functionOffset is %x\n",functionOffset); 684 // fprintf(stderr, "in addLocalFunctions vtableOffset is %x\n",vtableOffset); 685 // fflush(stderr); 686 687 for (sal_Int32 i = 0; i < type->nMembers; ++i) { 688 typelib_TypeDescription * member = 0; 689 TYPELIB_DANGER_GET(&member, type->ppMembers[i]); 690 OSL_ASSERT(member != 0); 691 switch (member->eTypeClass) { 692 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 693 // Getter: 694 (s++)->fn = code; 695 code = codeSnippet( 696 code, functionOffset++, vtableOffset, 697 bridges::cpp_uno::shared::isSimpleType( 698 reinterpret_cast< 699 typelib_InterfaceAttributeTypeDescription * >( 700 member)->pAttributeTypeRef)); 701 702 // Setter: 703 if (!reinterpret_cast< 704 typelib_InterfaceAttributeTypeDescription * >( 705 member)->bReadOnly) 706 { 707 (s++)->fn = code; 708 code = codeSnippet(code, functionOffset++, vtableOffset, true); 709 } 710 break; 711 712 case typelib_TypeClass_INTERFACE_METHOD: 713 (s++)->fn = code; 714 code = codeSnippet( 715 code, functionOffset++, vtableOffset, 716 bridges::cpp_uno::shared::isSimpleType( 717 reinterpret_cast< 718 typelib_InterfaceMethodTypeDescription * >( 719 member)->pReturnTypeRef)); 720 break; 721 722 default: 723 OSL_ASSERT(false); 724 break; 725 } 726 TYPELIB_DANGER_RELEASE(member); 727 } 728 return code; 729 } 730 731