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 <malloc.h> 28 29 #include <com/sun/star/uno/genfunc.hxx> 30 #include <uno/data.h> 31 32 #include "bridges/cpp_uno/shared/bridge.hxx" 33 #include "bridges/cpp_uno/shared/types.hxx" 34 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" 35 #include "bridges/cpp_uno/shared/vtables.hxx" 36 37 #include "share.hxx" 38 39 #include <stdio.h> 40 #include <string.h> 41 42 43 using namespace ::rtl; 44 using namespace ::com::sun::star::uno; 45 46 void MapReturn(long r0, typelib_TypeClass eTypeClass, sal_uInt64* pRegisterReturn) 47 { 48 register float fret asm("$f0"); 49 register double dret asm("$f0"); 50 51 #ifdef CMC_DEBUG 52 fprintf(stderr,"Mapping Return with %lx %ld %f\n", r0, r0, dret); 53 #endif 54 switch (eTypeClass) 55 { 56 case typelib_TypeClass_HYPER: 57 case typelib_TypeClass_UNSIGNED_HYPER: 58 *pRegisterReturn = r0; 59 break; 60 case typelib_TypeClass_LONG: 61 case typelib_TypeClass_UNSIGNED_LONG: 62 case typelib_TypeClass_ENUM: 63 *(unsigned int*)pRegisterReturn = (unsigned int)r0; 64 break; 65 case typelib_TypeClass_CHAR: 66 case typelib_TypeClass_SHORT: 67 case typelib_TypeClass_UNSIGNED_SHORT: 68 *(unsigned short*)pRegisterReturn = (unsigned short)r0; 69 break; 70 case typelib_TypeClass_BOOLEAN: 71 case typelib_TypeClass_BYTE: 72 *(unsigned char*)pRegisterReturn = (unsigned char)r0; 73 break; 74 case typelib_TypeClass_FLOAT: 75 *reinterpret_cast<float *>( pRegisterReturn ) = fret; 76 break; 77 case typelib_TypeClass_DOUBLE: 78 *reinterpret_cast<double *>( pRegisterReturn ) = dret; 79 break; 80 default: 81 break; 82 } 83 #ifdef CMC_DEBUG 84 fprintf(stderr, "end of MapReturn with %x\n", pRegisterReturn ? *pRegisterReturn : 0); 85 #endif 86 } 87 88 #define INSERT_FLOAT( pSV, nr, pFPR, pDS ) \ 89 { \ 90 if ( nr < axp::MAX_WORDS_IN_REGS ) \ 91 { \ 92 pFPR[nr++] = *reinterpret_cast<float *>( pSV ); \ 93 } \ 94 else \ 95 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); \ 96 } 97 98 #define INSERT_DOUBLE( pSV, nr, pFPR, pDS ) \ 99 if ( nr < axp::MAX_WORDS_IN_REGS ) \ 100 pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \ 101 else \ 102 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim! 103 104 #define INSERT_INT64( pSV, nr, pGPR, pDS ) \ 105 if ( nr < axp::MAX_WORDS_IN_REGS ) \ 106 pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \ 107 else \ 108 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); 109 110 #define INSERT_INT32( pSV, nr, pGPR, pDS ) \ 111 if ( nr < axp::MAX_WORDS_IN_REGS ) \ 112 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ 113 else \ 114 *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV ); 115 116 #define INSERT_INT16( pSV, nr, pGPR, pDS ) \ 117 if ( nr < axp::MAX_WORDS_IN_REGS ) \ 118 pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \ 119 else \ 120 *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV ); 121 122 #define INSERT_INT8( pSV, nr, pGPR, pDS ) \ 123 if ( nr < axp::MAX_WORDS_IN_REGS ) \ 124 pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \ 125 else \ 126 *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV ); 127 128 namespace 129 { 130 //================================================================================================== 131 void callVirtualMethod( 132 void * pThis, sal_Int32 nVtableIndex, 133 void * pRegisterReturn, typelib_TypeDescription * pReturnTypeDescr, 134 sal_uInt64 *pStack, sal_uInt32 nStack, 135 sal_uInt64 *pGPR, sal_uInt32 nGPR, 136 double *pFPR, sal_uInt32 nFPR) 137 { 138 // Should not happen, but... 139 if ( nFPR > axp::MAX_SSE_REGS ) 140 nFPR = axp::MAX_SSE_REGS; 141 if ( nGPR > axp::MAX_GPR_REGS ) 142 nGPR = axp::MAX_GPR_REGS; 143 144 #ifdef CMC_DEBUG 145 // Let's figure out what is really going on here 146 { 147 fprintf( stderr, "= nStack is %d\n", nStack ); 148 fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR ); 149 for ( unsigned int i = 0; i < nGPR; ++i ) 150 fprintf( stderr, "0x%lx, ", pGPR[i] ); 151 fprintf( stderr, "\nFPR's (%d): ", nFPR ); 152 for ( unsigned int i = 0; i < nFPR; ++i ) 153 fprintf( stderr, "0x%lx (%f), ", pFPR[i], pFPR[i] ); 154 fprintf( stderr, "\nStack (%d): ", nStack ); 155 for ( unsigned int i = 0; i < nStack; ++i ) 156 fprintf( stderr, "0x%lx, ", pStack[i] ); 157 fprintf( stderr, "\n" ); 158 fprintf( stderr, "pRegisterReturn is %p\n", pRegisterReturn); 159 } 160 #endif 161 162 // Load parameters to stack, if necessary 163 // Stack, if used, must be 8-bytes aligned 164 sal_uInt64 *stack = (sal_uInt64 *) __builtin_alloca( nStack * 8 ); 165 memcpy( stack, pStack, nStack * 8 ); 166 167 // To get pointer to method 168 // a) get the address of the vtable 169 sal_uInt64 pMethod = *((sal_uInt64 *)pThis); 170 // b) get the address from the vtable entry at offset 171 pMethod += 8 * nVtableIndex; 172 pMethod = *((sal_uInt64 *)pMethod); 173 174 typedef void (* FunctionCall )( sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64 ); 175 FunctionCall pFunc = (FunctionCall)pMethod; 176 177 switch (nFPR) //deliberate fall through 178 { 179 case 6: 180 asm volatile("ldt $f16,%0" :: "m"(pFPR[5]) : "$f16"); 181 case 5: 182 asm volatile("ldt $f17,%0" :: "m"(pFPR[4]) : "$f17"); 183 case 4: 184 asm volatile("ldt $f18,%0" :: "m"(pFPR[3]) : "$f18"); 185 case 3: 186 asm volatile("ldt $f19,%0" :: "m"(pFPR[2]) : "$f19"); 187 case 2: 188 asm volatile("ldt $f20,%0" :: "m"(pFPR[1]) : "$f20"); 189 case 1: 190 asm volatile("ldt $f21,%0" :: "m"(pFPR[0]) : "$f21"); 191 default: 192 break; 193 } 194 195 (*pFunc)(pGPR[0], pGPR[1], pGPR[2], pGPR[3], pGPR[4], pGPR[5]); 196 register sal_uInt64 r0 __asm__("$0"); 197 MapReturn(r0, pReturnTypeDescr->eTypeClass, (sal_uInt64*)pRegisterReturn); 198 } 199 200 201 //============================================================================ 202 static void cpp_call( 203 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, 204 bridges::cpp_uno::shared::VtableSlot aVtableSlot, 205 typelib_TypeDescriptionReference * pReturnTypeRef, 206 sal_Int32 nParams, typelib_MethodParameter * pParams, 207 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) 208 { 209 // max space for: [complex ret ptr], values|ptr ... 210 sal_uInt64 * pStack = (sal_uInt64 *)alloca( (nParams+3) * sizeof(sal_Int64) ); 211 sal_uInt64 * pStackStart = pStack; 212 213 sal_uInt64 pGPR[axp::MAX_GPR_REGS]; 214 double pFPR[axp::MAX_SSE_REGS]; 215 sal_uInt32 nRegs = 0; 216 217 // return 218 typelib_TypeDescription * pReturnTypeDescr = 0; 219 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); 220 OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); 221 222 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion 223 224 if (pReturnTypeDescr) 225 { 226 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) 227 { 228 pCppReturn = pUnoReturn; // direct way for simple types 229 } 230 else 231 { 232 // complex return via ptr 233 pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) 234 ? alloca( pReturnTypeDescr->nSize ) 235 : pUnoReturn); // direct way 236 INSERT_INT64( &pCppReturn, nRegs, pGPR, pStack ); 237 } 238 } 239 // push "this" pointer 240 void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset; 241 242 INSERT_INT64( &pAdjustedThisPtr, nRegs, pGPR, pStack ); 243 244 // stack space 245 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int64), "### unexpected size!" ); 246 // args 247 void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); 248 // indizes of values this have to be converted (interface conversion cpp<=>uno) 249 sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); 250 // type descriptions for reconversions 251 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); 252 253 sal_Int32 nTempIndizes = 0; 254 255 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 256 { 257 const typelib_MethodParameter & rParam = pParams[nPos]; 258 typelib_TypeDescription * pParamTypeDescr = 0; 259 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); 260 261 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) 262 { 263 uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr, 264 pThis->getBridge()->getUno2Cpp() ); 265 266 switch (pParamTypeDescr->eTypeClass) 267 { 268 case typelib_TypeClass_HYPER: 269 case typelib_TypeClass_UNSIGNED_HYPER: 270 INSERT_INT64( pCppArgs[nPos], nRegs, pGPR, pStack ); 271 break; 272 case typelib_TypeClass_LONG: 273 case typelib_TypeClass_UNSIGNED_LONG: 274 case typelib_TypeClass_ENUM: 275 INSERT_INT32( pCppArgs[nPos], nRegs, pGPR, pStack ); 276 break; 277 case typelib_TypeClass_SHORT: 278 case typelib_TypeClass_CHAR: 279 case typelib_TypeClass_UNSIGNED_SHORT: 280 INSERT_INT16( pCppArgs[nPos], nRegs, pGPR, pStack ); 281 break; 282 case typelib_TypeClass_BOOLEAN: 283 case typelib_TypeClass_BYTE: 284 INSERT_INT8( pCppArgs[nPos], nRegs, pGPR, pStack ); 285 break; 286 case typelib_TypeClass_FLOAT: 287 INSERT_FLOAT( pCppArgs[nPos], nRegs, pFPR, pStack ); 288 break; 289 case typelib_TypeClass_DOUBLE: 290 INSERT_DOUBLE( pCppArgs[nPos], nRegs, pFPR, pStack ); 291 break; 292 default: 293 break; 294 } 295 296 // no longer needed 297 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 298 } 299 else // ptr to complex value | ref 300 { 301 if (! rParam.bIn) // is pure out 302 { 303 // cpp out is constructed mem, uno out is not! 304 uno_constructData( 305 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), 306 pParamTypeDescr ); 307 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call 308 // will be released at reconversion 309 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 310 } 311 // is in/inout 312 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr )) 313 { 314 uno_copyAndConvertData( 315 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), 316 pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); 317 318 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted 319 // will be released at reconversion 320 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 321 } 322 else // direct way 323 { 324 pCppArgs[nPos] = pUnoArgs[nPos]; 325 // no longer needed 326 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 327 } 328 INSERT_INT64( &(pCppArgs[nPos]), nRegs, pGPR, pStack ); 329 } 330 } 331 332 try 333 { 334 callVirtualMethod( 335 pAdjustedThisPtr, aVtableSlot.index, 336 pCppReturn, pReturnTypeDescr, 337 pStackStart, (pStack - pStackStart), 338 pGPR, nRegs, 339 pFPR, nRegs ); 340 // NO exception occured... 341 *ppUnoExc = 0; 342 343 // reconvert temporary params 344 for ( ; nTempIndizes--; ) 345 { 346 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 347 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; 348 349 if (pParams[nIndex].bIn) 350 { 351 if (pParams[nIndex].bOut) // inout 352 { 353 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value 354 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, 355 pThis->getBridge()->getCpp2Uno() ); 356 } 357 } 358 else // pure out 359 { 360 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, 361 pThis->getBridge()->getCpp2Uno() ); 362 } 363 // destroy temp cpp param => cpp: every param was constructed 364 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); 365 366 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 367 } 368 // return value 369 if (pCppReturn && pUnoReturn != pCppReturn) 370 { 371 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, 372 pThis->getBridge()->getCpp2Uno() ); 373 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); 374 } 375 } 376 catch (...) 377 { 378 // fill uno exception 379 fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, 380 *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); 381 382 383 // temporary params 384 for ( ; nTempIndizes--; ) 385 { 386 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 387 // destroy temp cpp param => cpp: every param was constructed 388 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); 389 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); 390 } 391 // return type 392 if (pReturnTypeDescr) 393 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 394 } 395 } 396 } 397 398 namespace bridges { namespace cpp_uno { namespace shared { 399 400 void unoInterfaceProxyDispatch( 401 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, 402 void * pReturn, void * pArgs[], uno_Any ** ppException ) 403 { 404 #ifdef CMC_DEBUG 405 fprintf(stderr, "unoInterfaceProxyDispatch\n"); 406 #endif 407 408 409 // is my surrogate 410 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis 411 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy *> (pUnoI); 412 413 switch (pMemberDescr->eTypeClass) 414 { 415 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 416 { 417 418 VtableSlot aVtableSlot( 419 getVtableSlot( 420 reinterpret_cast< 421 typelib_InterfaceAttributeTypeDescription const * >( 422 pMemberDescr))); 423 424 if (pReturn) 425 { 426 // dependent dispatch 427 cpp_call( 428 pThis, aVtableSlot, 429 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, 430 0, 0, // no params 431 pReturn, pArgs, ppException ); 432 } 433 else 434 { 435 // is SET 436 typelib_MethodParameter aParam; 437 aParam.pTypeRef = 438 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; 439 aParam.bIn = sal_True; 440 aParam.bOut = sal_False; 441 442 typelib_TypeDescriptionReference * pReturnTypeRef = 0; 443 OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); 444 typelib_typedescriptionreference_new( 445 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); 446 447 // dependent dispatch 448 aVtableSlot.index += 1; //get then set method 449 cpp_call( 450 pThis, aVtableSlot, 451 pReturnTypeRef, 452 1, &aParam, 453 pReturn, pArgs, ppException ); 454 455 typelib_typedescriptionreference_release( pReturnTypeRef ); 456 } 457 458 break; 459 } 460 case typelib_TypeClass_INTERFACE_METHOD: 461 { 462 463 VtableSlot aVtableSlot( 464 getVtableSlot( 465 reinterpret_cast< 466 typelib_InterfaceMethodTypeDescription const * >( 467 pMemberDescr))); 468 switch (aVtableSlot.index) 469 { 470 // standard calls 471 case 1: // acquire uno interface 472 (*pUnoI->acquire)( pUnoI ); 473 *ppException = 0; 474 break; 475 case 2: // release uno interface 476 (*pUnoI->release)( pUnoI ); 477 *ppException = 0; 478 break; 479 case 0: // queryInterface() opt 480 { 481 typelib_TypeDescription * pTD = 0; 482 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); 483 if (pTD) 484 { 485 uno_Interface * pInterface = 0; 486 (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( 487 pThis->pBridge->getUnoEnv(), 488 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); 489 490 if (pInterface) 491 { 492 ::uno_any_construct( 493 reinterpret_cast< uno_Any * >( pReturn ), 494 &pInterface, pTD, 0 ); 495 (*pInterface->release)( pInterface ); 496 TYPELIB_DANGER_RELEASE( pTD ); 497 *ppException = 0; 498 break; 499 } 500 TYPELIB_DANGER_RELEASE( pTD ); 501 } 502 } // else perform queryInterface() 503 default: 504 // dependent dispatch 505 cpp_call( 506 pThis, aVtableSlot, 507 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, 508 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, 509 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, 510 pReturn, pArgs, ppException ); 511 } 512 break; 513 } 514 default: 515 { 516 ::com::sun::star::uno::RuntimeException aExc( 517 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), 518 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); 519 520 Type const & rExcType = ::getCppuType( &aExc ); 521 // binary identical null reference 522 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); 523 } 524 } 525 } 526 527 } } } 528 /* vi:set tabstop=4 shiftwidth=4 expandtab: */ 529