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 <sal/alloca.h> 32 33 #include <com/sun/star/uno/genfunc.hxx> 34 #include <uno/data.h> 35 #include <typelib/typedescription.hxx> 36 37 #include "bridges/cpp_uno/shared/bridge.hxx" 38 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" 39 #include "bridges/cpp_uno/shared/types.hxx" 40 #include "bridges/cpp_uno/shared/vtablefactory.hxx" 41 42 #include "cc50_solaris_sparc.hxx" 43 #include "flushcode.hxx" 44 45 using namespace com::sun::star::uno; 46 47 namespace 48 { 49 50 //================================================================================================== 51 static typelib_TypeClass cpp2uno_call( 52 bridges::cpp_uno::shared::CppInterfaceProxy * pThis, 53 const typelib_TypeDescription * pMemberTypeDescr, 54 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return 55 sal_Int32 nParams, typelib_MethodParameter * pParams, 56 void ** pCallStack, 57 sal_Int64 * pRegisterReturn /* space for register return */ ) 58 { 59 // pCallStack: [return ptr], this, params 60 char * pCppStack = (char *)pCallStack; 61 62 // return 63 typelib_TypeDescription * pReturnTypeDescr = 0; 64 if (pReturnTypeRef) 65 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); 66 67 void * pUnoReturn = 0; 68 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need 69 70 if (pReturnTypeDescr) 71 { 72 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) 73 { 74 pUnoReturn = pRegisterReturn; // direct way for simple types 75 } 76 else // complex return via ptr (pCppReturn) 77 { 78 pCppReturn = *pCallStack; 79 pCppStack += sizeof( void* ); 80 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( 81 pReturnTypeDescr ) 82 ? alloca( pReturnTypeDescr->nSize ) 83 : pCppReturn); // direct way 84 } 85 } 86 // pop this 87 pCppStack += sizeof( void* ); 88 89 // stack space 90 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); 91 // parameters 92 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); 93 void ** pCppArgs = pUnoArgs + nParams; 94 // indizes of values this have to be converted (interface conversion cpp<=>uno) 95 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); 96 // type descriptions for reconversions 97 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); 98 99 sal_Int32 nTempIndizes = 0; 100 101 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 102 { 103 const typelib_MethodParameter & rParam = pParams[nPos]; 104 typelib_TypeDescription * pParamTypeDescr = 0; 105 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); 106 107 if (!rParam.bOut 108 && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) 109 // value 110 { 111 pCppArgs[ nPos ] = pUnoArgs[ nPos ] = 112 CPPU_CURRENT_NAMESPACE::adjustPointer( 113 pCppStack, pParamTypeDescr ); 114 switch (pParamTypeDescr->eTypeClass) 115 { 116 case typelib_TypeClass_HYPER: 117 case typelib_TypeClass_UNSIGNED_HYPER: 118 case typelib_TypeClass_DOUBLE: 119 pCppStack += sizeof(sal_Int32); // extra long 120 } 121 // no longer needed 122 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 123 } 124 else // ptr to complex value | ref 125 { 126 pCppArgs[nPos] = *(void **)pCppStack; 127 128 if (! rParam.bIn) // is pure out 129 { 130 // uno out is unconstructed mem! 131 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); 132 pTempIndizes[nTempIndizes] = nPos; 133 // will be released at reconversion 134 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 135 } 136 // is in/inout 137 else if (bridges::cpp_uno::shared::relatesToInterfaceType( 138 pParamTypeDescr )) 139 { 140 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), 141 *(void **)pCppStack, pParamTypeDescr, 142 pThis->getBridge()->getCpp2Uno() ); 143 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted 144 // will be released at reconversion 145 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 146 } 147 else // direct way 148 { 149 pUnoArgs[nPos] = *(void **)pCppStack; 150 // no longer needed 151 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 152 } 153 } 154 pCppStack += sizeof(sal_Int32); // standard parameter length 155 } 156 157 // ExceptionHolder 158 uno_Any aUnoExc; // Any will be constructed by callee 159 uno_Any * pUnoExc = &aUnoExc; 160 161 // invoke uno dispatch call 162 (*pThis->getUnoI()->pDispatcher)( 163 pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); 164 165 // in case no exception occured... 166 if (pUnoExc) 167 { 168 // destruct temporary in/inout params 169 for ( ; nTempIndizes--; ) 170 { 171 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 172 173 if (pParams[nIndex].bIn) // is in/inout => was constructed 174 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); 175 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); 176 } 177 if (pReturnTypeDescr) 178 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 179 180 CPPU_CURRENT_NAMESPACE::cc50_solaris_sparc_raiseException( 181 &aUnoExc, pThis->getBridge()->getUno2Cpp() ); 182 // has to destruct the any 183 // is here for dummy 184 return typelib_TypeClass_VOID; 185 } 186 else // else no exception occured... 187 { 188 // temporary params 189 for ( ; nTempIndizes--; ) 190 { 191 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 192 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; 193 194 if (pParams[nIndex].bOut) // inout/out 195 { 196 // convert and assign 197 uno_destructData( 198 pCppArgs[nIndex], pParamTypeDescr, 199 reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); 200 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, 201 pThis->getBridge()->getUno2Cpp() ); 202 } 203 // destroy temp uno param 204 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); 205 206 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 207 } 208 // return 209 if (pCppReturn) // has complex return 210 { 211 if (pUnoReturn != pCppReturn) // needs reconversion 212 { 213 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, 214 pThis->getBridge()->getUno2Cpp() ); 215 // destroy temp uno return 216 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); 217 } 218 // complex return ptr is set to eax 219 *(void **)pRegisterReturn = pCppReturn; 220 } 221 if (pReturnTypeDescr) 222 { 223 typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; 224 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 225 return eRet; 226 } 227 else 228 return typelib_TypeClass_VOID; 229 } 230 } 231 232 233 //================================================================================================== 234 static typelib_TypeClass cpp_mediate( 235 sal_Int32 nFunctionIndex, 236 sal_Int32 nVtableOffset, 237 void ** pCallStack, 238 sal_Int64 * pRegisterReturn /* space for register return */ ) 239 { 240 OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); 241 242 // pCallStack: this, params 243 void * pThis; 244 if( nFunctionIndex & 0x80000000 ) 245 { 246 nFunctionIndex &= 0x7fffffff; 247 pThis = pCallStack[1]; 248 } 249 else 250 { 251 pThis = pCallStack[0]; 252 } 253 pThis = static_cast< char * >(pThis) - nVtableOffset; 254 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI 255 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( 256 pThis); 257 258 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); 259 260 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, 261 "### illegal vtable index!" ); 262 // if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) 263 // { 264 // RuntimeException aExc; 265 // aExc.Message = OUString::createFromAscii("illegal vtable index!"); 266 // aExc.Context = (XInterface *)pThis; 267 // throw aExc; 268 // } 269 270 // determine called method 271 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; 272 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); 273 274 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); 275 276 typelib_TypeClass eRet; 277 switch (aMemberDescr.get()->eTypeClass) 278 { 279 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 280 { 281 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) 282 { 283 // is GET method 284 eRet = cpp2uno_call( 285 pCppI, aMemberDescr.get(), 286 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, 287 0, 0, // no params 288 pCallStack, pRegisterReturn ); 289 } 290 else 291 { 292 // is SET method 293 typelib_MethodParameter aParam; 294 aParam.pTypeRef = 295 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; 296 aParam.bIn = sal_True; 297 aParam.bOut = sal_False; 298 299 eRet = cpp2uno_call( 300 pCppI, aMemberDescr.get(), 301 0, // indicates void return 302 1, &aParam, 303 pCallStack, pRegisterReturn ); 304 } 305 break; 306 } 307 case typelib_TypeClass_INTERFACE_METHOD: 308 { 309 // is METHOD 310 switch (nFunctionIndex) 311 { 312 // standard XInterface vtable calls 313 case 1: // acquire() 314 pCppI->acquireProxy(); // non virtual call! 315 eRet = typelib_TypeClass_VOID; 316 break; 317 case 2: // release() 318 pCppI->releaseProxy(); // non virtual call! 319 eRet = typelib_TypeClass_VOID; 320 break; 321 case 0: // queryInterface() opt 322 { 323 typelib_TypeDescription * pTD = 0; 324 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[2] )->getTypeLibType() ); 325 if (pTD) 326 { 327 XInterface * pInterface = 0; 328 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( 329 pCppI->getBridge()->getCppEnv(), 330 (void **)&pInterface, pCppI->getOid().pData, 331 (typelib_InterfaceTypeDescription *)pTD ); 332 333 if (pInterface) 334 { 335 ::uno_any_construct( 336 reinterpret_cast< uno_Any * >( pCallStack[0] ), 337 &pInterface, pTD, 338 reinterpret_cast< uno_AcquireFunc >(cpp_acquire) ); 339 pInterface->release(); 340 TYPELIB_DANGER_RELEASE( pTD ); 341 *(void **)pRegisterReturn = pCallStack[0]; 342 eRet = typelib_TypeClass_ANY; 343 break; 344 } 345 TYPELIB_DANGER_RELEASE( pTD ); 346 } 347 } // else perform queryInterface() 348 default: 349 eRet = cpp2uno_call( 350 pCppI, aMemberDescr.get(), 351 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, 352 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, 353 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, 354 pCallStack, pRegisterReturn ); 355 } 356 break; 357 } 358 // default: 359 // { 360 // RuntimeException aExc; 361 // aExc.Message = OUString::createFromAscii("no member description found!"); 362 // aExc.Context = (XInterface *)pThis; 363 // throw aExc; 364 // // is here for dummy 365 // eRet = typelib_TypeClass_VOID; 366 // } 367 } 368 369 return eRet; 370 } 371 372 } 373 374 //================================================================================================== 375 extern "C" int cpp_vtable_call( 376 int nFunctionIndex, int nVtableOffset, void** pCallStack ) 377 { 378 sal_Int64 nRegReturn; 379 typelib_TypeClass aType = cpp_mediate( 380 nFunctionIndex, nVtableOffset, pCallStack, &nRegReturn ); 381 OSL_ASSERT( sizeof(void *) == sizeof(sal_Int32) ); 382 switch( aType ) 383 { 384 // move return value into register space 385 // (will be loaded by machine code snippet) 386 // Use pCallStack[1/2] instead of pCallStack[0/1], because the former is 387 // properly dword aligned: 388 case typelib_TypeClass_BOOLEAN: 389 case typelib_TypeClass_BYTE: 390 pCallStack[1] = (void*)*(char*)&nRegReturn; 391 break; 392 case typelib_TypeClass_CHAR: 393 case typelib_TypeClass_SHORT: 394 case typelib_TypeClass_UNSIGNED_SHORT: 395 pCallStack[1] = (void*)*(short*)&nRegReturn; 396 break; 397 case typelib_TypeClass_DOUBLE: 398 case typelib_TypeClass_HYPER: 399 case typelib_TypeClass_UNSIGNED_HYPER: 400 // move long to %i1 401 pCallStack[2] = ((void **)&nRegReturn)[ 1 ]; 402 case typelib_TypeClass_FLOAT: 403 default: 404 // move long to %i0 405 pCallStack[1] = ((void **)&nRegReturn)[ 0 ]; 406 break; 407 } 408 return aType; 409 } 410 411 //================================================================================================== 412 namespace { 413 414 extern "C" void privateSnippetExecutor(); 415 416 int const codeSnippetSize = 7 * 4; 417 418 unsigned char * codeSnippet( 419 unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, 420 bool simpleRetType) 421 { 422 sal_uInt32 index = functionIndex; 423 if (!simpleRetType) { 424 index |= 0x80000000; 425 } 426 unsigned int * p = reinterpret_cast< unsigned int * >(code); 427 OSL_ASSERT(sizeof (unsigned int) == 4); 428 // save %sp, -96, %sp ! 92 byte minimal stack frame, + 4 byte dword align: 429 *p++ = 0x9DE3BFA0; 430 // sethi %hi(privateSnippetExecutor), %l0: 431 *p++ = 0x21000000 432 | (reinterpret_cast< unsigned int >(privateSnippetExecutor) >> 10); 433 // sethi %hi(index), %o0: 434 *p++ = 0x11000000 | (index >> 10); 435 // or %o0, %lo(index), %o0: 436 *p++ = 0x90122000 | (index & 0x3FF); 437 // sethi %hi(vtableOffset), %o1: 438 *p++ = 0x13000000 | (vtableOffset >> 10); 439 // jmpl %l0, %lo(privateSnippetExecutor), %g0: 440 *p++ = 0x81C42000 441 | (reinterpret_cast< unsigned int >(privateSnippetExecutor) & 0x3FF); 442 // or %o1, %lo(vtableOffset), %o1: 443 *p++ = 0x92126000 | (vtableOffset & 0x3FF); 444 OSL_ASSERT( 445 reinterpret_cast< unsigned char * >(p) - code <= codeSnippetSize); 446 return code + codeSnippetSize; 447 } 448 449 } 450 451 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; 452 453 bridges::cpp_uno::shared::VtableFactory::Slot * 454 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) 455 { 456 return static_cast< Slot * >(block) + 1; 457 } 458 459 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( 460 sal_Int32 slotCount) 461 { 462 return (slotCount + 3) * sizeof (Slot) + slotCount * codeSnippetSize; 463 } 464 465 bridges::cpp_uno::shared::VtableFactory::Slot * 466 bridges::cpp_uno::shared::VtableFactory::initializeBlock( 467 void * block, sal_Int32 slotCount) 468 { 469 Slot * slots = mapBlockToVtable(block) + 2; 470 slots[-3].fn = 0; // RTTI 471 slots[-2].fn = 0; // null 472 slots[-1].fn = 0; // destructor 473 return slots + slotCount; 474 } 475 476 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( 477 Slot ** slots, unsigned char * code, 478 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, 479 sal_Int32 functionCount, sal_Int32 vtableOffset) 480 { 481 (*slots) -= functionCount; 482 Slot * s = *slots; 483 for (sal_Int32 i = 0; i < type->nMembers; ++i) { 484 typelib_TypeDescription * member = 0; 485 TYPELIB_DANGER_GET(&member, type->ppMembers[i]); 486 OSL_ASSERT(member != 0); 487 switch (member->eTypeClass) { 488 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 489 // Getter: 490 (s++)->fn = code; 491 code = codeSnippet( 492 code, functionOffset++, vtableOffset, 493 bridges::cpp_uno::shared::isSimpleType( 494 reinterpret_cast< 495 typelib_InterfaceAttributeTypeDescription * >( 496 member)->pAttributeTypeRef)); 497 // Setter: 498 if (!reinterpret_cast< 499 typelib_InterfaceAttributeTypeDescription * >( 500 member)->bReadOnly) 501 { 502 (s++)->fn = code; 503 code = codeSnippet(code, functionOffset++, vtableOffset, true); 504 } 505 break; 506 507 case typelib_TypeClass_INTERFACE_METHOD: 508 (s++)->fn = code; 509 code = codeSnippet( 510 code, functionOffset++, vtableOffset, 511 bridges::cpp_uno::shared::isSimpleType( 512 reinterpret_cast< 513 typelib_InterfaceMethodTypeDescription * >( 514 member)->pReturnTypeRef)); 515 break; 516 517 default: 518 OSL_ASSERT(false); 519 break; 520 } 521 TYPELIB_DANGER_RELEASE(member); 522 } 523 return code; 524 } 525 526 void bridges::cpp_uno::shared::VtableFactory::flushCode( 527 unsigned char const * begin, unsigned char const * end) 528 { 529 bridges::cpp_uno::cc50_solaris_sparc::flushCode(begin, end); 530 } 531