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 #include <com/sun/star/uno/genfunc.hxx> 24 #include <typelib/typedescription.hxx> 25 #include <uno/data.h> 26 #include <osl/endian.h> 27 #include "bridges/cpp_uno/shared/bridge.hxx" 28 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" 29 #include "bridges/cpp_uno/shared/types.hxx" 30 #include "bridges/cpp_uno/shared/vtablefactory.hxx" 31 #include "share.hxx" 32 33 #include <stdio.h> 34 #include <string.h> 35 36 using namespace com::sun::star::uno; 37 38 //#define BRDEBUG 39 40 #ifdef BRDEBUG 41 #include <rtl/strbuf.hxx> 42 #include <rtl/ustrbuf.hxx> 43 #include <osl/diagnose.h> 44 #include <osl/mutex.hxx> 45 using namespace ::std; 46 using namespace ::osl; 47 using namespace ::rtl; 48 #endif 49 #include <sys/sysmips.h> 50 51 #ifdef OSL_BIGENDIAN 52 #define IS_BIG_ENDIAN 1 53 #else 54 #define IS_BIG_ENDIAN 0 55 #endif 56 57 using namespace ::com::sun::star::uno; 58 59 namespace 60 { 61 62 //================================================================================================== 63 static typelib_TypeClass cpp2uno_call( 64 bridges::cpp_uno::shared::CppInterfaceProxy * pThis, 65 const typelib_TypeDescription * pMemberTypeDescr, 66 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return 67 sal_Int32 nParams, typelib_MethodParameter * pParams, 68 void ** gpreg, void ** /*fpreg*/, void ** ovrflw, 69 sal_Int64 * pRegisterReturn /* space for register return */ ) 70 { 71 /* Most MIPS ABIs view the arguments as a struct, of which the 72 first N words go in registers and the rest go on the stack. If I < N, the 73 Ith word might go in Ith integer argument register or the Ith 74 floating-point one. For these ABIs, we only need to remember the number 75 of words passed so far. We are interested only in o32 ABI,so it is the 76 case. 77 */ 78 int nw = 0; // number of words used by arguments 79 80 #ifdef BRDEBUG 81 fprintf(stderr,"cpp2uno_call1\n"); 82 #endif 83 84 /* C++ has [ret *] or this as the first arguments, so no arguments will 85 * be passed in floating-point registers? 86 */ 87 //int int_seen = 0; // have we seen integer arguments? 88 89 void ** pCppStack; //temporary stack pointer 90 91 // gpreg: [ret *], this, [gpr params] 92 // fpreg: [fpr params] 93 // ovrflw: [gpr or fpr params (properly aligned)] 94 95 // return 96 typelib_TypeDescription * pReturnTypeDescr = 0; 97 if (pReturnTypeRef) 98 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); 99 100 void * pUnoReturn = 0; 101 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need 102 103 if (pReturnTypeDescr) 104 { 105 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) 106 { 107 pUnoReturn = pRegisterReturn; // direct way for simple types 108 #ifdef BRDEBUG 109 fprintf(stderr,"cpp2uno_call:simplereturn\n"); 110 #endif 111 } 112 else // complex return via ptr (pCppReturn) 113 { 114 pCppReturn = *(void **)gpreg; 115 gpreg++; 116 nw++; 117 118 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) 119 ? alloca( pReturnTypeDescr->nSize ) 120 : pCppReturn); // direct way 121 #ifdef BRDEBUG 122 fprintf(stderr,"cpp2uno_call:complexreturn\n"); 123 #endif 124 } 125 } 126 127 // pop this 128 gpreg++; 129 nw++; 130 131 // stack space 132 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); 133 // parameters 134 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); 135 void ** pCppArgs = pUnoArgs + nParams; 136 // indizes of values this have to be converted (interface conversion cpp<=>uno) 137 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); 138 // type descriptions for reconversions 139 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); 140 141 sal_Int32 nTempIndizes = 0; 142 143 #ifdef BRDEBUG 144 fprintf(stderr,"cpp2uno_call:nParams=%d\n",nParams); 145 #endif 146 147 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 148 { 149 const typelib_MethodParameter & rParam = pParams[nPos]; 150 typelib_TypeDescription * pParamTypeDescr = 0; 151 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); 152 153 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) 154 // value 155 { 156 157 switch (pParamTypeDescr->eTypeClass) 158 { 159 case typelib_TypeClass_DOUBLE: 160 case typelib_TypeClass_HYPER: 161 case typelib_TypeClass_UNSIGNED_HYPER: 162 #ifdef BRDEBUG 163 fprintf(stderr,"cpp2uno_call:hyper=%d,%p\n",pParamTypeDescr->eTypeClass,gpreg[0]); 164 #endif 165 if (nw < 3) { 166 if (nw & 1) { 167 nw++; 168 gpreg++; 169 } 170 #ifdef BRDEBUG 171 fprintf(stderr,"cpp2uno_call:gpreg=%p,%p\n",gpreg[0],gpreg[1]); 172 #endif 173 pCppArgs[nPos] = gpreg; 174 pUnoArgs[nPos] = gpreg; 175 nw += 2; 176 gpreg += 2; 177 } else { 178 if (((long)ovrflw) & 4) ovrflw++; 179 #ifdef BRDEBUG 180 fprintf(stderr,"cpp2uno_call:overflw=%p,%p\n",ovrflw[0],ovrflw[1]); 181 #endif 182 pCppArgs[nPos] = ovrflw; 183 pUnoArgs[nPos] = ovrflw; 184 ovrflw += 2; 185 } 186 break; 187 188 case typelib_TypeClass_BYTE: 189 case typelib_TypeClass_BOOLEAN: 190 #ifdef BRDEBUG 191 fprintf(stderr,"cpp2uno_call:byte=%p,%p\n",gpreg[0],ovrflw[0]); 192 #endif 193 if (nw < 4) { 194 pCppArgs[nPos] = ((char *)gpreg + 3*IS_BIG_ENDIAN); 195 pUnoArgs[nPos] = ((char *)gpreg + 3*IS_BIG_ENDIAN); 196 nw++; 197 gpreg++; 198 } else { 199 pCppArgs[nPos] = ((char *)ovrflw + 3*IS_BIG_ENDIAN); 200 pUnoArgs[nPos] = ((char *)ovrflw + 3*IS_BIG_ENDIAN); 201 ovrflw++; 202 } 203 break; 204 205 206 case typelib_TypeClass_CHAR: 207 case typelib_TypeClass_SHORT: 208 case typelib_TypeClass_UNSIGNED_SHORT: 209 #ifdef BRDEBUG 210 fprintf(stderr,"cpp2uno_call:char=%p,%p\n",gpreg[0],ovrflw[0]); 211 #endif 212 if (nw < 4) { 213 pCppArgs[nPos] = ((char *)gpreg + 2*IS_BIG_ENDIAN); 214 pUnoArgs[nPos] = ((char *)gpreg + 2*IS_BIG_ENDIAN); 215 nw++; 216 gpreg++; 217 } else { 218 pCppArgs[nPos] = ((char *)ovrflw + 2*IS_BIG_ENDIAN); 219 pUnoArgs[nPos] = ((char *)ovrflw + 2*IS_BIG_ENDIAN); 220 ovrflw++; 221 } 222 break; 223 224 225 default: 226 #ifdef BRDEBUG 227 fprintf(stderr,"cpp2uno_call:def=%p,%p\n",gpreg[0],ovrflw[0]); 228 #endif 229 if (nw < 4) { 230 pCppArgs[nPos] = gpreg; 231 pUnoArgs[nPos] = gpreg; 232 nw++; 233 gpreg++; 234 } else { 235 pCppArgs[nPos] = ovrflw; 236 pUnoArgs[nPos] = ovrflw; 237 ovrflw++; 238 } 239 break; 240 241 } 242 // no longer needed 243 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 244 } 245 else // ptr to complex value | ref 246 { 247 248 #ifdef BRDEBUG 249 fprintf(stderr,"cpp2uno_call:ptr|ref\n"); 250 #endif 251 if (nw < 4) { 252 pCppArgs[nPos] = *(void **)gpreg; 253 pCppStack = gpreg; 254 nw++; 255 gpreg++; 256 } else { 257 pCppArgs[nPos] = *(void **)ovrflw; 258 pCppStack = ovrflw; 259 ovrflw++; 260 } 261 #ifdef BRDEBUG 262 fprintf(stderr,"cpp2uno_call:pCppStack=%p\n",pCppStack); 263 #endif 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 #ifdef BRDEBUG 283 fprintf(stderr,"cpp2uno_call:related to interface,%p,%d,pUnoargs[%d]=%p\n",*(void**)pCppStack,pParamTypeDescr->nSize,nPos,pUnoArgs[nPos]); 284 #endif 285 } 286 else // direct way 287 { 288 pUnoArgs[nPos] = *(void **)pCppStack; 289 #ifdef BRDEBUG 290 fprintf(stderr,"cpp2uno_call:direct,pUnoArgs[%d]=%p\n",nPos,pUnoArgs[nPos]); 291 #endif 292 // no longer needed 293 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 294 } 295 } 296 } 297 #ifdef BRDEBUG 298 fprintf(stderr,"cpp2uno_call2,%p,unoargs=%p\n",pThis->getUnoI()->pDispatcher,pUnoArgs); 299 #endif 300 301 // ExceptionHolder 302 uno_Any aUnoExc; // Any will be constructed by callee 303 uno_Any * pUnoExc = &aUnoExc; 304 305 // invoke uno dispatch call 306 (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); 307 #ifdef BRDEBUG 308 fprintf(stderr,"cpp2uno_call2,after dispatch\n"); 309 #endif 310 311 // in case an exception occured... 312 if (pUnoExc) 313 { 314 // destruct temporary in/inout params 315 for ( ; nTempIndizes--; ) 316 { 317 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 318 319 if (pParams[nIndex].bIn) // is in/inout => was constructed 320 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); 321 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); 322 } 323 if (pReturnTypeDescr) 324 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 325 326 CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); 327 // has to destruct the any 328 // is here for dummy 329 return typelib_TypeClass_VOID; 330 } 331 else // else no exception occured... 332 { 333 // temporary params 334 for ( ; nTempIndizes--; ) 335 { 336 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 337 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; 338 339 if (pParams[nIndex].bOut) // inout/out 340 { 341 // convert and assign 342 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); 343 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, 344 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, pReturnTypeDescr, 357 pThis->getBridge()->getUno2Cpp() ); 358 // destroy temp uno return 359 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); 360 } 361 // complex return ptr is set to return reg 362 *(void **)pRegisterReturn = pCppReturn; 363 } 364 if (pReturnTypeDescr) 365 { 366 typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; 367 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 368 return eRet; 369 } 370 else 371 return typelib_TypeClass_VOID; 372 } 373 } 374 375 376 //================================================================================================== 377 static typelib_TypeClass cpp_mediate( 378 sal_Int32 nFunctionIndex, 379 sal_Int32 nVtableOffset, 380 void ** gpreg, void ** fpreg, void ** ovrflw, 381 sal_Int64 * pRegisterReturn /* space for register return */ ) 382 { 383 OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); 384 385 #ifdef BRDEBUG 386 fprintf(stderr,"cpp_mediate1 gp=%p,fp=%p,ov=%p\n",gpreg,fpreg,ovrflw); 387 fprintf(stderr,"gp=%x,%x,%x,%x\n",gpreg[0],gpreg[1],gpreg[2],gpreg[3]); 388 #endif 389 390 // gpreg: [ret *], this, [other gpr params] 391 // fpreg: [fpr params] 392 // ovrflw: [gpr or fpr params (properly aligned)] 393 394 void * pThis; 395 if (nFunctionIndex & 0x80000000 ) 396 { 397 nFunctionIndex &= 0x7fffffff; 398 pThis = gpreg[1]; 399 } 400 else 401 { 402 pThis = gpreg[0]; 403 } 404 #ifdef BRDEBUG 405 fprintf(stderr,"cpp_mediate12,pThis=%p, nFunctionIndex=%d,nVtableOffset=%d\n",pThis,nFunctionIndex,nVtableOffset); 406 #endif 407 408 pThis = static_cast< char * >(pThis) - nVtableOffset; 409 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI 410 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( 411 pThis); 412 #ifdef BRDEBUG 413 fprintf(stderr,"cpp_mediate13,pCppI=%p\n",pCppI); 414 #endif 415 416 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); 417 418 #ifdef BRDEBUG 419 fprintf(stderr,"cpp_mediate2\n"); 420 #endif 421 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); 422 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) 423 { 424 throw RuntimeException( 425 rtl::OUString::createFromAscii("illegal vtable index!"), 426 (XInterface *)pThis ); 427 } 428 429 // determine called method 430 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; 431 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); 432 433 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); 434 435 #ifdef BRDEBUG 436 fprintf(stderr,"cpp_mediate3\n"); 437 OString cstr( OUStringToOString( aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_ASCII_US ) ); 438 fprintf( stderr, "calling %s, nFunctionIndex=%d\n", cstr.getStr(), nFunctionIndex ); 439 #endif 440 typelib_TypeClass eRet; 441 switch (aMemberDescr.get()->eTypeClass) 442 { 443 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 444 { 445 #ifdef BRDEBUG 446 fprintf(stderr,"cpp_mediate4\n"); 447 #endif 448 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) 449 { 450 // is GET method 451 eRet = cpp2uno_call( 452 pCppI, aMemberDescr.get(), 453 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, 454 0, 0, // no params 455 gpreg, fpreg, ovrflw, pRegisterReturn ); 456 } 457 else 458 { 459 // is SET method 460 typelib_MethodParameter aParam; 461 aParam.pTypeRef = 462 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; 463 aParam.bIn = sal_True; 464 aParam.bOut = sal_False; 465 466 eRet = cpp2uno_call( 467 pCppI, aMemberDescr.get(), 468 0, // indicates void return 469 1, &aParam, 470 gpreg, fpreg, ovrflw, pRegisterReturn ); 471 } 472 break; 473 } 474 case typelib_TypeClass_INTERFACE_METHOD: 475 { 476 #ifdef BRDEBUG 477 fprintf(stderr,"cpp_mediate5\n"); 478 #endif 479 // is METHOD 480 switch (nFunctionIndex) 481 { 482 case 1: // acquire() 483 pCppI->acquireProxy(); // non virtual call! 484 eRet = typelib_TypeClass_VOID; 485 break; 486 case 2: // release() 487 #ifdef BRDEBUG 488 fprintf(stderr,"cpp_mediate51\n"); 489 #endif 490 pCppI->releaseProxy(); // non virtual call! 491 eRet = typelib_TypeClass_VOID; 492 #ifdef BRDEBUG 493 fprintf(stderr,"cpp_mediate52\n"); 494 #endif 495 break; 496 case 0: // queryInterface() opt 497 { 498 typelib_TypeDescription * pTD = 0; 499 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() ); 500 if (pTD) 501 { 502 XInterface * pInterface = 0; 503 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( 504 pCppI->getBridge()->getCppEnv(), 505 (void **)&pInterface, pCppI->getOid().pData, 506 (typelib_InterfaceTypeDescription *)pTD ); 507 508 if (pInterface) 509 { 510 ::uno_any_construct( 511 reinterpret_cast< uno_Any * >( gpreg[0] ), 512 &pInterface, pTD, cpp_acquire ); 513 pInterface->release(); 514 TYPELIB_DANGER_RELEASE( pTD ); 515 *(void **)pRegisterReturn = gpreg[0]; 516 eRet = typelib_TypeClass_ANY; 517 break; 518 } 519 TYPELIB_DANGER_RELEASE( pTD ); 520 } 521 } // else perform queryInterface() 522 default: 523 eRet = cpp2uno_call( 524 pCppI, aMemberDescr.get(), 525 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, 526 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, 527 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, 528 gpreg, fpreg, ovrflw, pRegisterReturn ); 529 } 530 break; 531 } 532 default: 533 { 534 #ifdef BRDEBUG 535 fprintf(stderr,"cpp_mediate6\n"); 536 #endif 537 throw RuntimeException( 538 rtl::OUString::createFromAscii("no member description found!"), 539 (XInterface *)pThis ); 540 // is here for dummy 541 eRet = typelib_TypeClass_VOID; 542 } 543 } 544 545 return eRet; 546 } 547 548 //================================================================================================== 549 /** 550 * is called on incoming vtable calls 551 * (called by asm snippets) 552 */ 553 // static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** fpregptr, void** ovrflw) 554 // static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** ovrflw) 555 static void cpp_vtable_call(void) 556 { 557 int nFunctionIndex; 558 int vTableOffset; 559 void** pCallStack; 560 void** ovrflw; 561 562 sal_Int32 gpreg[4]; 563 double fpreg[2]; 564 565 //memcpy( fpreg, fpregptr, 16); 566 567 volatile long nRegReturn[2]; 568 569 __asm__( "sw $4, %0\n\t" 570 "sw $5, %1\n\t" 571 "sw $6, %2\n\t" 572 "sw $7, %3\n\t" 573 ::"m"(nFunctionIndex), "m"(vTableOffset), "m"(pCallStack), "m"(ovrflw) ); 574 575 memcpy( gpreg, pCallStack, 16); 576 577 #ifdef BRDEBUG 578 fprintf(stderr,"in cpp_vtable_call nFunctionIndex is %d\n",nFunctionIndex); 579 fprintf(stderr,"in cpp_vtable_call nVtableOffset is %d\n",vTableOffset); 580 fprintf(stderr,"gp=%x,%x,%x,%x\n",gpreg[0],gpreg[1],gpreg[2],gpreg[3]); 581 #endif 582 583 //sal_Bool bComplex = nFunctionIndex & 0x80000000 ? sal_True : sal_False; 584 585 typelib_TypeClass aType = 586 cpp_mediate( nFunctionIndex, vTableOffset, (void**)gpreg, (void**)fpreg, ovrflw, (sal_Int64*)nRegReturn ); 587 588 switch( aType ) 589 { 590 591 // move return value into register space 592 // (will be loaded by machine code snippet) 593 594 case typelib_TypeClass_BOOLEAN: 595 case typelib_TypeClass_BYTE: 596 __asm__( "lbu $2,%0\n\t" : : 597 "m"(nRegReturn[0]) ); 598 break; 599 600 case typelib_TypeClass_CHAR: 601 case typelib_TypeClass_UNSIGNED_SHORT: 602 __asm__( "lhu $2,%0\n\t" : : 603 "m"(nRegReturn[0]) ); 604 break; 605 606 case typelib_TypeClass_SHORT: 607 __asm__( "lh $2,%0\n\t" : : 608 "m"(nRegReturn[0]) ); 609 break; 610 611 612 case typelib_TypeClass_FLOAT: 613 __asm__( "lwc1 $f0,%0\n\t" : : 614 "m" (*((float*)nRegReturn)) ); 615 break; 616 617 case typelib_TypeClass_DOUBLE: 618 { register double dret asm("$f0"); 619 dret = (*((double*)nRegReturn)); } 620 break; 621 622 case typelib_TypeClass_HYPER: 623 case typelib_TypeClass_UNSIGNED_HYPER: 624 __asm__( "lw $3,%0\n\t" : : 625 "m"(nRegReturn[1]) ); // fall through 626 627 default: 628 __asm__( "lw $2,%0\n\t" : : 629 "m"(nRegReturn[0]) ); 630 break; 631 } 632 } 633 634 635 int const codeSnippetSize = 56; 636 637 unsigned char * codeSnippet( unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, 638 bool simpleRetType) 639 { 640 641 #ifdef BRDEBUG 642 fprintf(stderr,"in codeSnippet functionIndex is %d\n", functionIndex); 643 fprintf(stderr,"in codeSnippet vtableOffset is %d\n", vtableOffset); 644 fflush(stderr); 645 #endif 646 647 if (! simpleRetType ) 648 functionIndex |= 0x80000000; 649 650 unsigned long * p = (unsigned long *) code; 651 652 // OSL_ASSERT( sizeof (long) == 4 ); 653 OSL_ASSERT((((unsigned long)code) & 0x3) == 0 ); //aligned to 4 otherwise a mistake 654 655 /* generate this code */ 656 /* 657 #save regs into argument space required by mips abi 658 c: afa40000 sw a0,0(sp) 659 10: afa50004 sw a1,4(sp) 660 14: afa60008 sw a2,8(sp) 661 18: afa7000c sw a3,12(sp) 662 #a0=index 663 1c: 3c040000 lui a0,0x0 664 20: 34840000 ori a0,a0,0x0 665 #a1=offset 666 24: 3c050000 lui a1,0x0 667 28: 34a50000 ori a1,a1,0x0 668 #a2=gpregptr 669 2c: 27a60000 addiu a2,sp,0 670 #a3=ovrflw 671 30: 27a70010 addiu a3,sp,16 672 #load cpp_vtable_call addr 673 34: 3c190000 lui t9,0x0 674 38: 37390000 ori t9,t9,0 675 #jmp to the function,note: we don't use jalr, that will destroy $ra 676 #but be sure to use t9! gp calculation depends on it 677 3c: 03200008 jr t9 678 40: 00000000 nop 679 680 be careful, we use the argument space reserved by the caller to 681 write down regs. This can avoid the need to make use of arbitary far away 682 stack space or to allocate a function frame for this code snippet itself. 683 Since only functions with variable arguments will overwrite the space, 684 cpp_vtable_call should be safe. 685 ??? gcc seems change this behavior! cpp_vtable_call overwrite the space! 686 */ 687 688 * p++ = 0xafa40000; 689 * p++ = 0xafa50004; 690 * p++ = 0xafa60008; 691 * p++ = 0xafa7000c; 692 * p++ = 0x3c040000 | ((functionIndex>>16) & 0x0000ffff); 693 * p++ = 0x34840000 | (functionIndex & 0x0000ffff); 694 * p++ = 0x3c050000 | ((vtableOffset>>16) & 0x0000ffff); 695 * p++ = 0x34a50000 | (vtableOffset & 0x0000ffff); 696 * p++ = 0x27a60000; 697 * p++ = 0x27a70010; 698 * p++ = 0x3c190000 | ((((unsigned long)cpp_vtable_call) >> 16) & 0x0000ffff); 699 * p++ = 0x37390000 | (((unsigned long)cpp_vtable_call) & 0x0000FFFF); 700 * p++ = 0x03200008; 701 * p++ = 0x00000000; 702 return (code + codeSnippetSize); 703 704 } 705 706 707 } 708 709 710 #define MIN_LINE_SIZE 32 711 712 void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * /*bptr*/, unsigned char const * /*eptr*/) 713 { 714 sysmips(FLUSH_CACHE,0,0,0); 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 726 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( 727 sal_Int32 slotCount) 728 { 729 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; 730 } 731 732 bridges::cpp_uno::shared::VtableFactory::Slot * 733 bridges::cpp_uno::shared::VtableFactory::initializeBlock( 734 void * block, sal_Int32 slotCount) 735 { 736 Slot * slots = mapBlockToVtable(block); 737 slots[-2].fn = 0; //null 738 slots[-1].fn = 0; //destructor 739 return slots + slotCount; 740 } 741 742 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( 743 Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, 744 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, 745 sal_Int32 functionCount, sal_Int32 vtableOffset) 746 { 747 (*slots) -= functionCount; 748 Slot * s = *slots; 749 #ifdef BRDEBUG 750 fprintf(stderr, "in addLocalFunctions functionOffset is %d\n",functionOffset); 751 fprintf(stderr, "in addLocalFunctions vtableOffset is %d\n",vtableOffset); 752 fprintf(stderr, "nMembers=%d\n",type->nMembers); 753 fflush(stderr); 754 #endif 755 756 for (sal_Int32 i = 0; i < type->nMembers; ++i) { 757 typelib_TypeDescription * member = 0; 758 TYPELIB_DANGER_GET(&member, type->ppMembers[i]); 759 OSL_ASSERT(member != 0); 760 switch (member->eTypeClass) { 761 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 762 // Getter: 763 (s++)->fn = code + writetoexecdiff; 764 code = codeSnippet( 765 code, functionOffset++, vtableOffset, 766 bridges::cpp_uno::shared::isSimpleType( 767 reinterpret_cast< 768 typelib_InterfaceAttributeTypeDescription * >( 769 member)->pAttributeTypeRef)); 770 771 // Setter: 772 if (!reinterpret_cast< 773 typelib_InterfaceAttributeTypeDescription * >( 774 member)->bReadOnly) 775 { 776 (s++)->fn = code + writetoexecdiff; 777 code = codeSnippet(code, functionOffset++, vtableOffset, true); 778 } 779 break; 780 781 case typelib_TypeClass_INTERFACE_METHOD: 782 (s++)->fn = code + writetoexecdiff; 783 code = codeSnippet( 784 code, functionOffset++, vtableOffset, 785 bridges::cpp_uno::shared::isSimpleType( 786 reinterpret_cast< 787 typelib_InterfaceMethodTypeDescription * >( 788 member)->pReturnTypeRef)); 789 break; 790 791 default: 792 OSL_ASSERT(false); 793 break; 794 } 795 TYPELIB_DANGER_RELEASE(member); 796 } 797 return code; 798 } 799 800