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