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 <string.h> 32 33 #include <com/sun/star/uno/genfunc.hxx> 34 #include <uno/data.h> 35 #include <typelib/typedescription.hxx> 36 37 #include "bridges/cpp_uno/shared/bridge.hxx" 38 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" 39 #include "bridges/cpp_uno/shared/types.hxx" 40 #include "bridges/cpp_uno/shared/vtablefactory.hxx" 41 42 #include "share.hxx" 43 // #include <stdio.h> 44 45 46 using namespace ::com::sun::star::uno; 47 48 namespace 49 { 50 51 //================================================================================================== 52 static typelib_TypeClass cpp2uno_call( 53 bridges::cpp_uno::shared::CppInterfaceProxy * pThis, 54 const typelib_TypeDescription * pMemberTypeDescr, 55 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return 56 sal_Int32 nParams, typelib_MethodParameter * pParams, 57 void ** gpreg, void ** fpreg, void ** ovrflw, 58 sal_Int64 * pRegisterReturn /* space for register return */ ) 59 { 60 int ng = 0; //number of gpr registers used 61 #ifndef __NO_FPRS__ 62 int nf = 0; //number of fpr regsiters used 63 #endif 64 void ** pCppStack; //temporary stack pointer 65 66 // gpreg: [ret *], this, [gpr params] 67 // fpreg: [fpr params] 68 // ovrflw: [gpr or fpr params (properly aligned)] 69 70 // return 71 typelib_TypeDescription * pReturnTypeDescr = 0; 72 if (pReturnTypeRef) 73 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); 74 75 void * pUnoReturn = 0; 76 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need 77 78 if (pReturnTypeDescr) 79 { 80 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) 81 { 82 pUnoReturn = pRegisterReturn; // direct way for simple types 83 } 84 else // complex return via ptr (pCppReturn) 85 { 86 pCppReturn = *(void **)gpreg; 87 gpreg++; 88 ng++; 89 90 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) 91 ? alloca( pReturnTypeDescr->nSize ) 92 : pCppReturn); // direct way 93 } 94 } 95 // pop this 96 gpreg++; 97 ng++; 98 99 // stack space 100 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); 101 // parameters 102 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); 103 void ** pCppArgs = pUnoArgs + nParams; 104 // indizes of values this have to be converted (interface conversion cpp<=>uno) 105 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); 106 // type descriptions for reconversions 107 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); 108 109 sal_Int32 nTempIndizes = 0; 110 111 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 112 { 113 const typelib_MethodParameter & rParam = pParams[nPos]; 114 typelib_TypeDescription * pParamTypeDescr = 0; 115 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); 116 117 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) 118 // value 119 { 120 121 switch (pParamTypeDescr->eTypeClass) 122 { 123 124 case typelib_TypeClass_DOUBLE: 125 #ifndef __NO_FPRS__ 126 if (nf < 8) { 127 pCppArgs[nPos] = fpreg; 128 pUnoArgs[nPos] = fpreg; 129 nf++; 130 fpreg += 2; 131 #else 132 if (ng & 1) { 133 ng++; 134 gpreg++; 135 } 136 if (ng < 8) { 137 pCppArgs[nPos] = gpreg; 138 pUnoArgs[nPos] = gpreg; 139 ng += 2; 140 gpreg += 2; 141 #endif 142 } else { 143 if (((long)ovrflw) & 4) ovrflw++; 144 pCppArgs[nPos] = ovrflw; 145 pUnoArgs[nPos] = ovrflw; 146 ovrflw += 2; 147 } 148 break; 149 150 case typelib_TypeClass_FLOAT: 151 // fpreg are all double values so need to 152 // modify fpreg to be a single word float value 153 #ifndef __NO_FPRS__ 154 if (nf < 8) { 155 float tmp = (float) (*((double *)fpreg)); 156 (*((float *) fpreg)) = tmp; 157 pCppArgs[nPos] = fpreg; 158 pUnoArgs[nPos] = fpreg; 159 nf++; 160 fpreg += 2; 161 #else 162 if (ng < 8) { 163 pCppArgs[nPos] = gpreg; 164 pUnoArgs[nPos] = gpreg; 165 ng++; 166 gpreg++; 167 #endif 168 } else { 169 #if 0 /* abi is not being followed correctly */ 170 if (((long)ovrflw) & 4) ovrflw++; 171 float tmp = (float) (*((double *)ovrflw)); 172 (*((float *) ovrflw)) = tmp; 173 pCppArgs[nPos] = ovrflw; 174 pUnoArgs[nPos] = ovrflw; 175 ovrflw += 2; 176 #else 177 pCppArgs[nPos] = ovrflw; 178 pUnoArgs[nPos] = ovrflw; 179 ovrflw += 1; 180 #endif 181 } 182 break; 183 184 case typelib_TypeClass_HYPER: 185 case typelib_TypeClass_UNSIGNED_HYPER: 186 if (ng & 1) { 187 ng++; 188 gpreg++; 189 } 190 if (ng < 8) { 191 pCppArgs[nPos] = gpreg; 192 pUnoArgs[nPos] = gpreg; 193 ng += 2; 194 gpreg += 2; 195 } else { 196 if (((long)ovrflw) & 4) ovrflw++; 197 pCppArgs[nPos] = ovrflw; 198 pUnoArgs[nPos] = ovrflw; 199 ovrflw += 2; 200 } 201 break; 202 203 case typelib_TypeClass_BYTE: 204 case typelib_TypeClass_BOOLEAN: 205 if (ng < 8) { 206 pCppArgs[nPos] = (((char *)gpreg) + 3); 207 pUnoArgs[nPos] = (((char *)gpreg) + 3); 208 ng++; 209 gpreg++; 210 } else { 211 pCppArgs[nPos] = (((char *)ovrflw) + 3); 212 pUnoArgs[nPos] = (((char *)ovrflw) + 3); 213 ovrflw++; 214 } 215 break; 216 217 218 case typelib_TypeClass_CHAR: 219 case typelib_TypeClass_SHORT: 220 case typelib_TypeClass_UNSIGNED_SHORT: 221 if (ng < 8) { 222 pCppArgs[nPos] = (((char *)gpreg)+ 2); 223 pUnoArgs[nPos] = (((char *)gpreg)+ 2); 224 ng++; 225 gpreg++; 226 } else { 227 pCppArgs[nPos] = (((char *)ovrflw) + 2); 228 pUnoArgs[nPos] = (((char *)ovrflw) + 2); 229 ovrflw++; 230 } 231 break; 232 233 234 default: 235 if (ng < 8) { 236 pCppArgs[nPos] = gpreg; 237 pUnoArgs[nPos] = gpreg; 238 ng++; 239 gpreg++; 240 } else { 241 pCppArgs[nPos] = ovrflw; 242 pUnoArgs[nPos] = ovrflw; 243 ovrflw++; 244 } 245 break; 246 247 } 248 // no longer needed 249 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 250 } 251 else // ptr to complex value | ref 252 { 253 254 if (ng < 8) { 255 pCppArgs[nPos] = *(void **)gpreg; 256 pCppStack = gpreg; 257 ng++; 258 gpreg++; 259 } else { 260 pCppArgs[nPos] = *(void **)ovrflw; 261 pCppStack = ovrflw; 262 ovrflw++; 263 } 264 265 if (! rParam.bIn) // is pure out 266 { 267 // uno out is unconstructed mem! 268 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); 269 pTempIndizes[nTempIndizes] = nPos; 270 // will be released at reconversion 271 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 272 } 273 // is in/inout 274 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) 275 { 276 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), 277 *(void **)pCppStack, pParamTypeDescr, 278 pThis->getBridge()->getCpp2Uno() ); 279 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted 280 // will be released at reconversion 281 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 282 } 283 else // direct way 284 { 285 pUnoArgs[nPos] = *(void **)pCppStack; 286 // no longer needed 287 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 288 } 289 } 290 } 291 292 // ExceptionHolder 293 uno_Any aUnoExc; // Any will be constructed by callee 294 uno_Any * pUnoExc = &aUnoExc; 295 296 // invoke uno dispatch call 297 (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); 298 299 // in case an exception occured... 300 if (pUnoExc) 301 { 302 // destruct temporary in/inout params 303 for ( ; nTempIndizes--; ) 304 { 305 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 306 307 if (pParams[nIndex].bIn) // is in/inout => was constructed 308 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); 309 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); 310 } 311 if (pReturnTypeDescr) 312 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 313 314 CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); 315 // has to destruct the any 316 // is here for dummy 317 return typelib_TypeClass_VOID; 318 } 319 else // else no exception occured... 320 { 321 // temporary params 322 for ( ; nTempIndizes--; ) 323 { 324 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 325 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; 326 327 if (pParams[nIndex].bOut) // inout/out 328 { 329 // convert and assign 330 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); 331 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, 332 pThis->getBridge()->getUno2Cpp() ); 333 } 334 // destroy temp uno param 335 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); 336 337 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 338 } 339 // return 340 if (pCppReturn) // has complex return 341 { 342 if (pUnoReturn != pCppReturn) // needs reconversion 343 { 344 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, 345 pThis->getBridge()->getUno2Cpp() ); 346 // destroy temp uno return 347 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); 348 } 349 // complex return ptr is set to return reg 350 *(void **)pRegisterReturn = pCppReturn; 351 } 352 if (pReturnTypeDescr) 353 { 354 typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; 355 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 356 return eRet; 357 } 358 else 359 return typelib_TypeClass_VOID; 360 } 361 } 362 363 364 //================================================================================================== 365 static typelib_TypeClass cpp_mediate( 366 sal_Int32 nFunctionIndex, 367 sal_Int32 nVtableOffset, 368 void ** gpreg, void ** fpreg, void ** ovrflw, 369 sal_Int64 * pRegisterReturn /* space for register return */ ) 370 { 371 OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); 372 373 // gpreg: [ret *], this, [other gpr params] 374 // fpreg: [fpr params] 375 // ovrflw: [gpr or fpr params (properly aligned)] 376 377 void * pThis; 378 if (nFunctionIndex & 0x80000000 ) 379 { 380 nFunctionIndex &= 0x7fffffff; 381 pThis = gpreg[1]; 382 } 383 else 384 { 385 pThis = gpreg[0]; 386 } 387 388 pThis = static_cast< char * >(pThis) - nVtableOffset; 389 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI 390 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( 391 pThis); 392 393 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); 394 395 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); 396 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) 397 { 398 throw RuntimeException( 399 rtl::OUString::createFromAscii("illegal vtable index!"), 400 (XInterface *)pThis ); 401 } 402 403 // determine called method 404 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; 405 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); 406 407 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); 408 409 typelib_TypeClass eRet; 410 switch (aMemberDescr.get()->eTypeClass) 411 { 412 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 413 { 414 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) 415 { 416 // is GET method 417 eRet = cpp2uno_call( 418 pCppI, aMemberDescr.get(), 419 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, 420 0, 0, // no params 421 gpreg, fpreg, ovrflw, pRegisterReturn ); 422 } 423 else 424 { 425 // is SET method 426 typelib_MethodParameter aParam; 427 aParam.pTypeRef = 428 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; 429 aParam.bIn = sal_True; 430 aParam.bOut = sal_False; 431 432 eRet = cpp2uno_call( 433 pCppI, aMemberDescr.get(), 434 0, // indicates void return 435 1, &aParam, 436 gpreg, fpreg, ovrflw, pRegisterReturn ); 437 } 438 break; 439 } 440 case typelib_TypeClass_INTERFACE_METHOD: 441 { 442 // is METHOD 443 switch (nFunctionIndex) 444 { 445 case 1: // acquire() 446 pCppI->acquireProxy(); // non virtual call! 447 eRet = typelib_TypeClass_VOID; 448 break; 449 case 2: // release() 450 pCppI->releaseProxy(); // non virtual call! 451 eRet = typelib_TypeClass_VOID; 452 break; 453 case 0: // queryInterface() opt 454 { 455 typelib_TypeDescription * pTD = 0; 456 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() ); 457 if (pTD) 458 { 459 XInterface * pInterface = 0; 460 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( 461 pCppI->getBridge()->getCppEnv(), 462 (void **)&pInterface, pCppI->getOid().pData, 463 (typelib_InterfaceTypeDescription *)pTD ); 464 465 if (pInterface) 466 { 467 ::uno_any_construct( 468 reinterpret_cast< uno_Any * >( gpreg[0] ), 469 &pInterface, pTD, cpp_acquire ); 470 pInterface->release(); 471 TYPELIB_DANGER_RELEASE( pTD ); 472 *(void **)pRegisterReturn = gpreg[0]; 473 eRet = typelib_TypeClass_ANY; 474 break; 475 } 476 TYPELIB_DANGER_RELEASE( pTD ); 477 } 478 } // else perform queryInterface() 479 default: 480 eRet = cpp2uno_call( 481 pCppI, aMemberDescr.get(), 482 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, 483 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, 484 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, 485 gpreg, fpreg, ovrflw, pRegisterReturn ); 486 } 487 break; 488 } 489 default: 490 { 491 throw RuntimeException( 492 rtl::OUString::createFromAscii("no member description found!"), 493 (XInterface *)pThis ); 494 // is here for dummy 495 eRet = typelib_TypeClass_VOID; 496 } 497 } 498 499 return eRet; 500 } 501 502 //================================================================================================== 503 /** 504 * is called on incoming vtable calls 505 * (called by asm snippets) 506 */ 507 static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** fpregptr, void** ovrflw) 508 { 509 sal_Int32 gpreg[8]; 510 memcpy( gpreg, gpregptr, 32); 511 512 #ifndef __NO_FPRS__ 513 double fpreg[8]; 514 memcpy( fpreg, fpregptr, 64); 515 #endif 516 517 volatile long nRegReturn[2]; 518 519 // fprintf(stderr,"in cpp_vtable_call nFunctionIndex is %x\n",nFunctionIndex); 520 // fprintf(stderr,"in cpp_vtable_call nVtableOffset is %x\n",nVtableOffset); 521 // fflush(stderr); 522 523 typelib_TypeClass aType = 524 cpp_mediate( nFunctionIndex, nVtableOffset, (void**)gpreg, 525 #ifndef __NO_FPRS__ 526 (void**)fpreg, 527 #else 528 NULL, 529 #endif 530 ovrflw, (sal_Int64*)nRegReturn ); 531 532 switch( aType ) 533 { 534 535 // move return value into register space 536 // (will be loaded by machine code snippet) 537 538 case typelib_TypeClass_BOOLEAN: 539 case typelib_TypeClass_BYTE: 540 __asm__( "lbz 3,%0\n\t" : : 541 "m"(nRegReturn[0]) ); 542 break; 543 544 case typelib_TypeClass_CHAR: 545 case typelib_TypeClass_SHORT: 546 case typelib_TypeClass_UNSIGNED_SHORT: 547 __asm__( "lhz 3,%0\n\t" : : 548 "m"(nRegReturn[0]) ); 549 break; 550 551 case typelib_TypeClass_FLOAT: 552 #ifndef __NO_FPRS__ 553 __asm__( "lfs 1,%0\n\t" : : 554 "m" (*((float*)nRegReturn)) ); 555 #else 556 __asm__( "lwz 3,%0\n\t" : : 557 "m"(nRegReturn[0]) ); 558 #endif 559 break; 560 561 case typelib_TypeClass_DOUBLE: 562 #ifndef __NO_FPRS__ 563 __asm__( "lfd 1,%0\n\t" : : 564 "m" (*((double*)nRegReturn)) ); 565 #else 566 __asm__( "lwz 3,%0\n\t" : : 567 "m"(nRegReturn[0]) ); 568 __asm__( "lwz 4,%0\n\t" : : 569 "m"(nRegReturn[1]) ); 570 #endif 571 break; 572 573 case typelib_TypeClass_HYPER: 574 case typelib_TypeClass_UNSIGNED_HYPER: 575 __asm__( "lwz 4,%0\n\t" : : 576 "m"(nRegReturn[1]) ); // fall through 577 578 default: 579 __asm__( "lwz 3,%0\n\t" : : 580 "m"(nRegReturn[0]) ); 581 break; 582 } 583 } 584 585 586 int const codeSnippetSize = 108; 587 588 unsigned char * codeSnippet( unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, 589 bool simpleRetType) 590 { 591 592 // fprintf(stderr,"in codeSnippet functionIndex is %x\n", functionIndex); 593 // fprintf(stderr,"in codeSnippet vtableOffset is %x\n", vtableOffset); 594 // fflush(stderr); 595 596 if (! simpleRetType ) 597 functionIndex |= 0x80000000; 598 599 unsigned long * p = (unsigned long *) code; 600 601 // OSL_ASSERT( sizeof (long) == 4 ); 602 OSL_ASSERT((((unsigned long)code) & 0x3) == 0 ); //aligned to 4 otherwise a mistake 603 604 /* generate this code */ 605 // # so first save gpr 3 to gpr 10 (aligned to 4) 606 // stw r3,-2048(r1) 607 // stw r4,-2044(r1) 608 // stw r5,-2040(r1) 609 // stw r6,-2036(r1) 610 // stw r7,-2032(r1) 611 // stw r8,-2028(r1) 612 // stw r9,-2024(r1) 613 // stw r10,-2020(r1) 614 615 616 // # next save fpr 1 to fpr 8 (aligned to 8) 617 // if dedicated floating point registers are used 618 // stfd f1,-2016(r1) 619 // stfd f2,-2008(r1) 620 // stfd f3,-2000(r1) 621 // stfd f4,-1992(r1) 622 // stfd f5,-1984(r1) 623 // stfd f6,-1976(r1) 624 // stfd f7,-1968(r1) 625 // stfd f8,-1960(r1) 626 627 // # now here is where cpp_vtable_call must go 628 // lis r3,-8531 629 // ori r3,r3,48879 630 // mtctr r3 631 632 // # now load up the functionIndex 633 // lis r3,-8531 634 // ori r3,r3,48879 635 636 // # now load up the vtableOffset 637 // lis r4,-8531 638 // ori r4,r4,48879 639 640 // #now load up the pointer to the saved gpr registers 641 // addi r5,r1,-2048 642 643 // #now load up the pointer to the saved fpr registers 644 // addi r6,r1,-2016 645 // if no dedicated floating point registers are used than we have NULL 646 // pointer there 647 // li r6, 0 648 // 649 650 // #now load up the pointer to the overflow call stack 651 // addi r7,r1,8 652 // bctr 653 654 * p++ = 0x9061f800; 655 * p++ = 0x9081f804; 656 * p++ = 0x90a1f808; 657 * p++ = 0x90c1f80c; 658 * p++ = 0x90e1f810; 659 * p++ = 0x9101f814; 660 * p++ = 0x9121f818; 661 * p++ = 0x9141f81c; 662 #ifndef __NO_FPRS__ 663 * p++ = 0xd821f820; 664 * p++ = 0xd841f828; 665 * p++ = 0xd861f830; 666 * p++ = 0xd881f838; 667 * p++ = 0xd8a1f840; 668 * p++ = 0xd8c1f848; 669 * p++ = 0xd8e1f850; 670 * p++ = 0xd901f858; 671 #else 672 /* these nops could be replaced with a smaller codeSnippetSize - 8 * 4 */ 673 * p++ = 0x60000000; 674 * p++ = 0x60000000; 675 * p++ = 0x60000000; 676 * p++ = 0x60000000; 677 * p++ = 0x60000000; 678 * p++ = 0x60000000; 679 * p++ = 0x60000000; 680 * p++ = 0x60000000; 681 #endif 682 * p++ = 0x3c600000 | (((unsigned long)cpp_vtable_call) >> 16); 683 * p++ = 0x60630000 | (((unsigned long)cpp_vtable_call) & 0x0000FFFF); 684 * p++ = 0x7c6903a6; 685 * p++ = 0x3c600000 | (((unsigned long)functionIndex) >> 16); 686 * p++ = 0x60630000 | (((unsigned long)functionIndex) & 0x0000FFFF); 687 * p++ = 0x3c800000 | (((unsigned long)vtableOffset) >> 16); 688 * p++ = 0x60840000 | (((unsigned long)vtableOffset) & 0x0000FFFF); 689 * p++ = 0x38a1f800; 690 #ifndef __NO_FPRS__ 691 * p++ = 0x38c1f820; 692 #else 693 * p++ = 0x38c00000; 694 #endif 695 * p++ = 0x38e10008; 696 * p++ = 0x4e800420; 697 return (code + codeSnippetSize); 698 699 } 700 701 702 } 703 704 void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * bptr, unsigned char const * eptr) 705 { 706 int const lineSize = 32; 707 for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) { 708 __asm__ volatile ("dcbst 0, %0" : : "r"(p) : "memory"); 709 } 710 __asm__ volatile ("sync" : : : "memory"); 711 for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) { 712 __asm__ volatile ("icbi 0, %0" : : "r"(p) : "memory"); 713 } 714 __asm__ volatile ("isync" : : : "memory"); 715 } 716 717 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; 718 719 bridges::cpp_uno::shared::VtableFactory::Slot * 720 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) 721 { 722 return static_cast< Slot * >(block) + 2; 723 } 724 725 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( 726 sal_Int32 slotCount) 727 { 728 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; 729 } 730 731 bridges::cpp_uno::shared::VtableFactory::Slot * 732 bridges::cpp_uno::shared::VtableFactory::initializeBlock( 733 void * block, sal_Int32 slotCount) 734 { 735 Slot * slots = mapBlockToVtable(block); 736 slots[-2].fn = 0; 737 slots[-1].fn = 0; 738 return slots + slotCount; 739 } 740 741 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( 742 Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, 743 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, 744 sal_Int32 functionCount, sal_Int32 vtableOffset) 745 { 746 (*slots) -= functionCount; 747 Slot * s = *slots; 748 // fprintf(stderr, "in addLocalFunctions functionOffset is %x\n",functionOffset); 749 // fprintf(stderr, "in addLocalFunctions vtableOffset is %x\n",vtableOffset); 750 // fflush(stderr); 751 752 for (sal_Int32 i = 0; i < type->nMembers; ++i) { 753 typelib_TypeDescription * member = 0; 754 TYPELIB_DANGER_GET(&member, type->ppMembers[i]); 755 OSL_ASSERT(member != 0); 756 switch (member->eTypeClass) { 757 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 758 // Getter: 759 (s++)->fn = code + writetoexecdiff; 760 code = codeSnippet( 761 code, functionOffset++, vtableOffset, 762 bridges::cpp_uno::shared::isSimpleType( 763 reinterpret_cast< 764 typelib_InterfaceAttributeTypeDescription * >( 765 member)->pAttributeTypeRef)); 766 767 // Setter: 768 if (!reinterpret_cast< 769 typelib_InterfaceAttributeTypeDescription * >( 770 member)->bReadOnly) 771 { 772 (s++)->fn = code + writetoexecdiff; 773 code = codeSnippet(code, functionOffset++, vtableOffset, true); 774 } 775 break; 776 777 case typelib_TypeClass_INTERFACE_METHOD: 778 (s++)->fn = code + writetoexecdiff; 779 code = codeSnippet( 780 code, functionOffset++, vtableOffset, 781 bridges::cpp_uno::shared::isSimpleType( 782 reinterpret_cast< 783 typelib_InterfaceMethodTypeDescription * >( 784 member)->pReturnTypeRef)); 785 break; 786 787 default: 788 OSL_ASSERT(false); 789 break; 790 } 791 TYPELIB_DANGER_RELEASE(member); 792 } 793 return code; 794 } 795 796