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 #include <malloc.h> 29 #include <hash_map> 30 31 #include <rtl/alloc.h> 32 #include <osl/mutex.hxx> 33 34 #include <com/sun/star/uno/genfunc.hxx> 35 #include "com/sun/star/uno/RuntimeException.hpp" 36 #include <uno/data.h> 37 #include <typelib/typedescription.hxx> 38 39 #include "bridges/cpp_uno/shared/bridge.hxx" 40 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" 41 #include "bridges/cpp_uno/shared/types.hxx" 42 #include "bridges/cpp_uno/shared/vtablefactory.hxx" 43 44 #include "share.hxx" 45 46 #include <dlfcn.h> 47 48 49 using namespace ::osl; 50 using namespace ::rtl; 51 using namespace ::com::sun::star::uno; 52 53 namespace 54 { 55 56 static typelib_TypeClass cpp2uno_call( 57 bridges::cpp_uno::shared::CppInterfaceProxy* pThis, 58 const typelib_TypeDescription * pMemberTypeDescr, 59 typelib_TypeDescriptionReference * pReturnTypeRef, 60 sal_Int32 nParams, typelib_MethodParameter * pParams, 61 long r8, void ** gpreg, double *fpreg, void ** ovrflw, 62 sal_Int64 * pRegisterReturn /* space for register return */ ) 63 { 64 void ** startovrflw = ovrflw; 65 int nregs = 0; //number of words passed in registers 66 67 #ifdef CMC_DEBUG 68 fprintf(stderr, "cpp2uno_call\n"); 69 #endif 70 // return 71 typelib_TypeDescription * pReturnTypeDescr = 0; 72 if (pReturnTypeRef) 73 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); 74 75 void * pUnoReturn = 0; 76 // complex return ptr: if != 0 && != pUnoReturn, reconversion need 77 void * pCppReturn = 0; 78 79 if (pReturnTypeDescr) 80 { 81 if (hppa::isRegisterReturn(pReturnTypeRef)) 82 { 83 #ifdef CMC_DEBUG 84 fprintf(stderr, "simple return\n"); 85 #endif 86 pUnoReturn = pRegisterReturn; // direct way for simple types 87 } 88 else 89 { 90 #ifdef CMC_DEBUG 91 fprintf(stderr, "complex return via r8\n"); 92 #endif 93 pCppReturn = (void *)r8; 94 95 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) 96 ? alloca( pReturnTypeDescr->nSize ) 97 : pCppReturn); // direct way 98 } 99 } 100 // pop this 101 gpreg++; 102 fpreg++; 103 nregs++; 104 105 // stack space 106 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); 107 // parameters 108 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); 109 void ** pCppArgs = pUnoArgs + nParams; 110 // indizes of values this have to be converted (interface conversion 111 // cpp<=>uno) 112 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); 113 // type descriptions for reconversions 114 typelib_TypeDescription ** ppTempParamTypeDescr = 115 (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); 116 117 sal_Int32 nTempIndizes = 0; 118 bool bOverFlowUsed = false; 119 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 120 { 121 const typelib_MethodParameter & rParam = pParams[nPos]; 122 typelib_TypeDescription * pParamTypeDescr = 0; 123 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); 124 125 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) 126 { 127 switch (pParamTypeDescr->eTypeClass) 128 { 129 case typelib_TypeClass_DOUBLE: 130 if (nregs < hppa::MAX_WORDS_IN_REGS && (nregs & 1)) 131 { 132 gpreg++; 133 fpreg++; 134 nregs++; 135 } 136 if (nregs < hppa::MAX_WORDS_IN_REGS-1) 137 { 138 fpreg++; 139 pCppArgs[nPos] = pUnoArgs[nPos] = fpreg; 140 gpreg+=2; 141 fpreg+=2; 142 nregs+=2; 143 } 144 else 145 { 146 if ((startovrflw-ovrflw) & 1) 147 ovrflw--; 148 pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)ovrflw - 4); 149 bOverFlowUsed = true; 150 } 151 if (bOverFlowUsed) ovrflw-=2; 152 break; 153 case typelib_TypeClass_FLOAT: 154 if (nregs < hppa::MAX_WORDS_IN_REGS) 155 { 156 pCppArgs[nPos] = pUnoArgs[nPos] = fpreg; 157 gpreg++; 158 fpreg++; 159 nregs++; 160 } 161 else 162 { 163 pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; 164 bOverFlowUsed = true; 165 } 166 if (bOverFlowUsed) ovrflw--; 167 break; 168 case typelib_TypeClass_HYPER: 169 case typelib_TypeClass_UNSIGNED_HYPER: 170 if (nregs < hppa::MAX_WORDS_IN_REGS && (nregs & 1)) 171 { 172 gpreg++; 173 fpreg++; 174 nregs++; 175 } 176 if (nregs < hppa::MAX_WORDS_IN_REGS-1) 177 { 178 pCppArgs[nPos] = pUnoArgs[nPos] = gpreg; 179 gpreg+=2; 180 fpreg+=2; 181 nregs+=2; 182 } 183 else 184 { 185 if ((startovrflw-ovrflw) & 1) 186 ovrflw--; 187 pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)ovrflw - 4); 188 bOverFlowUsed = true; 189 } 190 if (bOverFlowUsed) ovrflw-=2; 191 break; 192 case typelib_TypeClass_BYTE: 193 case typelib_TypeClass_BOOLEAN: 194 if (nregs < hppa::MAX_WORDS_IN_REGS) 195 { 196 pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)gpreg + 3); 197 gpreg++; 198 fpreg++; 199 nregs++; 200 } 201 else 202 { 203 pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)ovrflw+3); 204 bOverFlowUsed = true; 205 } 206 if (bOverFlowUsed) ovrflw--; 207 break; 208 case typelib_TypeClass_CHAR: 209 case typelib_TypeClass_SHORT: 210 case typelib_TypeClass_UNSIGNED_SHORT: 211 if (nregs < hppa::MAX_WORDS_IN_REGS) 212 { 213 pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)gpreg+2); 214 gpreg++; 215 fpreg++; 216 nregs++; 217 } 218 else 219 { 220 pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)ovrflw+2); 221 bOverFlowUsed = true; 222 } 223 if (bOverFlowUsed) ovrflw--; 224 break; 225 case typelib_TypeClass_ENUM: 226 case typelib_TypeClass_LONG: 227 case typelib_TypeClass_UNSIGNED_LONG: 228 default: 229 if (nregs < hppa::MAX_WORDS_IN_REGS) 230 { 231 pCppArgs[nPos] = pUnoArgs[nPos] = gpreg; 232 gpreg++; 233 fpreg++; 234 nregs++; 235 } 236 else 237 { 238 pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw; 239 bOverFlowUsed = true; 240 } 241 if (bOverFlowUsed) ovrflw--; 242 break; 243 } 244 // no longer needed 245 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 246 } 247 else // ptr to complex value | ref 248 { 249 void *pCppStack; 250 251 if (nregs < hppa::MAX_WORDS_IN_REGS) 252 { 253 pCppArgs[nPos] = pCppStack = *gpreg; 254 gpreg++; 255 fpreg++; 256 nregs++; 257 } 258 else 259 { 260 pCppArgs[nPos] = pCppStack = *ovrflw; 261 bOverFlowUsed = true; 262 } 263 if (bOverFlowUsed) ovrflw--; 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( 275 pParamTypeDescr )) 276 { 277 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), 278 pCppStack, pParamTypeDescr, 279 pThis->getBridge()->getCpp2Uno() ); 280 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted 281 // will be released at reconversion 282 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 283 } 284 else // direct way 285 { 286 pUnoArgs[nPos] = pCppStack; 287 // no longer needed 288 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 289 } 290 } 291 } 292 293 // ExceptionHolder 294 uno_Any aUnoExc; // Any will be constructed by callee 295 uno_Any * pUnoExc = &aUnoExc; 296 297 #ifdef CMC_DEBUG 298 fprintf(stderr, "before dispatch\n"); 299 #endif 300 // invoke uno dispatch call 301 (*pThis->getUnoI()->pDispatcher)( 302 pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); 303 304 #ifdef CMC_DEBUG 305 fprintf(stderr, "after dispatch\n"); 306 #endif 307 308 // in case an exception occured... 309 if (pUnoExc) 310 { 311 // destruct temporary in/inout params 312 for ( ; nTempIndizes--; ) 313 { 314 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 315 316 if (pParams[nIndex].bIn) // is in/inout => was constructed 317 uno_destructData( pUnoArgs[nIndex], 318 ppTempParamTypeDescr[nTempIndizes], 0 ); 319 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); 320 } 321 if (pReturnTypeDescr) 322 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 323 324 CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, 325 pThis->getBridge()->getUno2Cpp() ); // has to destruct the any 326 // is here for dummy 327 return typelib_TypeClass_VOID; 328 } 329 else // else no exception occured... 330 { 331 // temporary params 332 for ( ; nTempIndizes--; ) 333 { 334 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 335 typelib_TypeDescription * pParamTypeDescr = 336 ppTempParamTypeDescr[nTempIndizes]; 337 338 if (pParams[nIndex].bOut) // inout/out 339 { 340 // convert and assign 341 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, 342 cpp_release ); 343 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], 344 pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); 345 } 346 // destroy temp uno param 347 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); 348 349 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 350 } 351 // return 352 if (pCppReturn) // has complex return 353 { 354 if (pUnoReturn != pCppReturn) // needs reconversion 355 { 356 uno_copyAndConvertData( pCppReturn, pUnoReturn, 357 pReturnTypeDescr, pThis->getBridge()->getUno2Cpp() ); 358 // destroy temp uno return 359 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); 360 } 361 // complex return ptr is set to eax 362 *(void **)pRegisterReturn = pCppReturn; 363 } 364 if (pReturnTypeDescr) 365 { 366 typelib_TypeClass eRet = 367 (typelib_TypeClass)pReturnTypeDescr->eTypeClass; 368 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 369 return eRet; 370 } 371 else 372 return typelib_TypeClass_VOID; 373 } 374 } 375 376 377 //===================================================================== 378 static typelib_TypeClass cpp_mediate( 379 sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, 380 void ** gpreg, double* fpreg, 381 long sp, long r8, 382 sal_Int64 * pRegisterReturn /* space for register return */ ) 383 384 { 385 void ** ovrflw = (void**)(sp); 386 #ifdef CMC_DEBUG 387 fprintf(stderr, "cpp_mediate with\n"); 388 fprintf(stderr, "%x %x\n", nFunctionIndex, nVtableOffset); 389 fprintf(stderr, "and %x %x\n", (long)(ovrflw[0]), (long)(ovrflw[-1])); 390 fprintf(stderr, "and %x %x\n", (long)(ovrflw[-2]), (long)(ovrflw[-3])); 391 fprintf(stderr, "and %x %x\n", (long)(ovrflw[-4]), (long)(ovrflw[-5])); 392 fprintf(stderr, "and %x %x\n", (long)(ovrflw[-6]), (long)(ovrflw[-7])); 393 fprintf(stderr, "and %x %x\n", (long)(ovrflw[-8]), (long)(ovrflw[-9])); 394 fprintf(stderr, "and %x %x\n", (long)(ovrflw[-10]), (long)(ovrflw[-11])); 395 fprintf(stderr, "and %x %x\n", (long)(ovrflw[-12]), (long)(ovrflw[-13])); 396 fprintf(stderr, "and %x %x\n", (long)(ovrflw[-14]), (long)(ovrflw[-15])); 397 #endif 398 OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); 399 400 // gpreg: [ret *], this, [other gpr params] 401 // fpreg: [fpr params] 402 // ovrflw: [gpr or fpr params (properly aligned)] 403 404 void * pThis; 405 if (nFunctionIndex & 0x80000000 ) 406 { 407 nFunctionIndex &= 0x7fffffff; 408 pThis = gpreg[1]; 409 #ifdef CMC_DEBUG 410 fprintf(stderr, "pThis is gpreg[1]\n"); 411 #endif 412 } 413 else 414 { 415 pThis = gpreg[0]; 416 #ifdef CMC_DEBUG 417 fprintf(stderr, "pThis is gpreg[0]\n"); 418 #endif 419 } 420 421 pThis = static_cast< char * >(pThis) - nVtableOffset; 422 423 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI = 424 bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( 425 pThis); 426 427 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); 428 429 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, 430 "### illegal vtable index!" ); 431 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) 432 { 433 throw RuntimeException( 434 OUString::createFromAscii("illegal vtable index!"), 435 (XInterface *)pCppI ); 436 } 437 438 // determine called method 439 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, 440 "### illegal vtable index!" ); 441 sal_Int32 nMemberPos = 442 pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; 443 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, 444 "### illegal member index!" ); 445 446 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); 447 448 typelib_TypeClass eRet; 449 switch (aMemberDescr.get()->eTypeClass) 450 { 451 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 452 { 453 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == 454 nFunctionIndex) 455 { 456 // is GET method 457 eRet = cpp2uno_call( 458 pCppI, aMemberDescr.get(), 459 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, 460 0, 0, // no params 461 r8, gpreg, fpreg, ovrflw, pRegisterReturn ); 462 } 463 else 464 { 465 // is SET method 466 typelib_MethodParameter aParam; 467 aParam.pTypeRef = 468 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; 469 aParam.bIn = sal_True; 470 aParam.bOut = sal_False; 471 472 eRet = cpp2uno_call( 473 pCppI, aMemberDescr.get(), 474 0, // indicates void return 475 1, &aParam, 476 r8, gpreg, fpreg, ovrflw, pRegisterReturn ); 477 } 478 break; 479 } 480 case typelib_TypeClass_INTERFACE_METHOD: 481 { 482 // is METHOD 483 switch (nFunctionIndex) 484 { 485 case 1: // acquire() 486 pCppI->acquireProxy(); // non virtual call! 487 eRet = typelib_TypeClass_VOID; 488 break; 489 case 2: // release() 490 pCppI->releaseProxy(); // non virtual call! 491 eRet = typelib_TypeClass_VOID; 492 break; 493 case 0: // queryInterface() opt 494 { 495 typelib_TypeDescription * pTD = 0; 496 TYPELIB_DANGER_GET(&pTD, 497 reinterpret_cast<Type *>(gpreg[1])->getTypeLibType()); 498 if (pTD) 499 { 500 XInterface * pInterface = 0; 501 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( 502 pCppI->getBridge()->getCppEnv(), 503 (void **)&pInterface, pCppI->getOid().pData, 504 (typelib_InterfaceTypeDescription *)pTD ); 505 506 if (pInterface) 507 { 508 ::uno_any_construct( 509 reinterpret_cast< uno_Any * >( r8 ), 510 &pInterface, pTD, cpp_acquire ); 511 pInterface->release(); 512 TYPELIB_DANGER_RELEASE( pTD ); 513 *(void **)pRegisterReturn = (void*)r8; 514 eRet = typelib_TypeClass_ANY; 515 break; 516 } 517 TYPELIB_DANGER_RELEASE( pTD ); 518 } 519 } // else perform queryInterface() 520 default: 521 eRet = cpp2uno_call( 522 pCppI, aMemberDescr.get(), 523 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, 524 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, 525 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, 526 r8, gpreg, fpreg, ovrflw, pRegisterReturn ); 527 } 528 break; 529 } 530 default: 531 { 532 throw RuntimeException( 533 OUString::createFromAscii("no member description found!"), 534 (XInterface *)pCppI ); 535 // is here for dummy 536 eRet = typelib_TypeClass_VOID; 537 } 538 } 539 540 return eRet; 541 } 542 } 543 544 //======================================================================= 545 /** 546 * is called on incoming vtable calls 547 * (called by asm snippets) 548 */ 549 550 sal_Int64 cpp_vtable_call( sal_uInt32 in0, sal_uInt32 in1, sal_uInt32 in2, sal_uInt32 in3, sal_uInt32 firstonstack ) 551 { 552 register sal_Int32 r21 asm("r21"); 553 register sal_Int32 r22 asm("r22"); 554 register sal_Int32 r28 asm("r28"); 555 sal_Int32 functionIndex = r21; 556 sal_Int32 vtableOffset = r22; 557 sal_Int32 r8 = r28; 558 559 long sp = (long)&firstonstack; 560 561 sal_uInt32 gpreg[hppa::MAX_GPR_REGS]; 562 gpreg[0] = in0; 563 gpreg[1] = in1; 564 gpreg[2] = in2; 565 gpreg[3] = in3; 566 567 float fpreg[hppa::MAX_SSE_REGS]; //todo 568 register float f0 asm("fr4"); fpreg[0] = f0; 569 register float f1 asm("fr5"); fpreg[1] = f1; 570 register float f2 asm("fr6"); fpreg[2] = f2; 571 register float f3 asm("fr7"); fpreg[3] = f3; 572 573 double dpreg[hppa::MAX_SSE_REGS]; //todo 574 register double d0 asm("fr4"); dpreg[0] = d0; 575 register double d1 asm("fr5"); dpreg[1] = d1; 576 register double d2 asm("fr6"); dpreg[2] = d2; 577 register double d3 asm("fr7"); dpreg[3] = d3; 578 579 580 #ifdef CMC_DEBUG 581 fprintf(stderr, "got to cpp_vtable_call with %x %x\n", functionIndex, vtableOffset); 582 for (int i = 0; i < hppa::MAX_GPR_REGS; ++i) 583 fprintf(stderr, "reg %d is %d %x\n", i, gpreg[i], gpreg[i]); 584 for (int i = 0; i < hppa::MAX_SSE_REGS; ++i) 585 fprintf(stderr, "float reg %d is %f %x\n", i, fpreg[i], ((long*)fpreg)[i]); 586 for (int i = 0; i < 4; ++i) 587 fprintf(stderr, "double reg %d is %f %llx\n", i, dpreg[i], ((long long*)dpreg)[i]); 588 #endif 589 590 sal_Int64 nRegReturn; 591 592 typelib_TypeClass aType = 593 cpp_mediate( functionIndex, vtableOffset, (void**)gpreg, dpreg, sp, r8, &nRegReturn); 594 595 switch( aType ) 596 { 597 case typelib_TypeClass_FLOAT: 598 f0 = (*((float*)&nRegReturn)); 599 break; 600 case typelib_TypeClass_DOUBLE: 601 d0 = (*((double*)&nRegReturn)); 602 break; 603 default: 604 break; 605 } 606 607 return nRegReturn; 608 } 609 610 611 namespace 612 { 613 const int codeSnippetSize = 44; 614 615 # define unldil(v) (((v & 0x7c) << 14) | ((v & 0x180) << 7) | ((v & 0x3) << 12) | ((v & 0xffe00) >> 8) | ((v & 0x100000) >> 20)) 616 # define L21(v) unldil(((unsigned long)(v) >> 11) & 0x1fffff) //Left 21 bits 617 # define R11(v) (((unsigned long)(v) & 0x7FF) << 1) //Right 11 bits 618 619 unsigned char *codeSnippet(unsigned char* code, sal_Int32 functionIndex, 620 sal_Int32 vtableOffset, bool bHasHiddenParam) 621 { 622 if (bHasHiddenParam) 623 functionIndex |= 0x80000000; 624 625 unsigned char * p = code; 626 *(unsigned long*)&p[0] = 0xeaa00000; // b,l 0x8,r21 627 *(unsigned long*)&p[4] = 0xd6a01c1e; // depwi 0,31,2,r21 628 *(unsigned long*)&p[8] = 0x4aa10040; // ldw 32(r21),r1 629 630 *(unsigned long*)&p[12] = 0x22A00000 | L21(functionIndex); // ldil L<functionIndex>,r21 631 *(unsigned long*)&p[16] = 0x36B50000 | R11(functionIndex); // ldo R<functionIndex>,r21 632 633 *(unsigned long*)&p[20] = 0x22C00000 | L21(vtableOffset); // ldil L<vtableOffset>,r22 634 *(unsigned long*)&p[24] = 0x36D60000 | R11(vtableOffset); // ldo R<vtableOffset>,r22 635 636 *(unsigned long*)&p[28] = 0x0c201094; // ldw 0(r1),r20 637 *(unsigned long*)&p[32] = 0xea80c000; // bv r0(r20) 638 *(unsigned long*)&p[36] = 0x0c281093; // ldw 4(r1),r19 639 *(unsigned long*)&p[40] = ((unsigned long)(cpp_vtable_call) & ~2); 640 641 return code + codeSnippetSize; 642 } 643 } 644 645 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; 646 647 bridges::cpp_uno::shared::VtableFactory::Slot * 648 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) 649 { 650 return static_cast< Slot * >(block) + 2; 651 } 652 653 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( 654 sal_Int32 slotCount) 655 { 656 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; 657 } 658 659 bridges::cpp_uno::shared::VtableFactory::Slot * 660 bridges::cpp_uno::shared::VtableFactory::initializeBlock( 661 void * block, sal_Int32 slotCount) 662 { 663 Slot * slots = mapBlockToVtable(block); 664 slots[-2].fn = 0; 665 slots[-1].fn = 0; 666 return slots + slotCount; 667 } 668 669 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( 670 Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, 671 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, 672 sal_Int32 functionCount, sal_Int32 vtableOffset) 673 { 674 (*slots) -= functionCount; 675 Slot * s = *slots; 676 for (sal_Int32 i = 0; i < type->nMembers; ++i) 677 { 678 typelib_TypeDescription * member = 0; 679 TYPELIB_DANGER_GET(&member, type->ppMembers[i]); 680 OSL_ASSERT(member != 0); 681 switch (member->eTypeClass) 682 { 683 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 684 // Getter: 685 (s++)->fn = code + writetoexecdiff; 686 code = codeSnippet(code, functionOffset++, vtableOffset, false); 687 // Setter: 688 if (!reinterpret_cast< 689 typelib_InterfaceAttributeTypeDescription * >( 690 member)->bReadOnly) 691 { 692 (s++)->fn = code + writetoexecdiff; 693 code = codeSnippet(code, functionOffset++, vtableOffset, false); 694 } 695 break; 696 case typelib_TypeClass_INTERFACE_METHOD: 697 { 698 (s++)->fn = code + writetoexecdiff; 699 code = codeSnippet(code, functionOffset++, vtableOffset, false); 700 break; 701 } 702 default: 703 OSL_ASSERT(false); 704 break; 705 } 706 TYPELIB_DANGER_RELEASE(member); 707 } 708 return code; 709 } 710 711 void bridges::cpp_uno::shared::VtableFactory::flushCode( 712 unsigned char const *beg, unsigned char const *end) 713 { 714 void *p = (void*)((size_t)beg & ~31); 715 size_t stride = 32; 716 while (p < end) 717 { 718 asm volatile("fdc (%0)\n\t" 719 "sync\n\t" 720 "fic,m %1(%%sr4, %0)\n\t" 721 "sync" : "+r"(p) : "r"(stride) : "memory"); 722 } 723 } 724 725 /* vi:set tabstop=4 shiftwidth=4 expandtab: */ 726