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