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