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