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