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 "precompiled_bridges.hxx" 25 #include "sal/config.h" 26 27 #include <cstddef> 28 #include <cstdlib> 29 #include <cstring> 30 31 #include "bridges/cpp_uno/shared/bridge.hxx" 32 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" 33 #include "bridges/cpp_uno/shared/types.hxx" 34 #include "bridges/cpp_uno/shared/vtablefactory.hxx" 35 #include "com/sun/star/uno/genfunc.hxx" 36 #include "osl/diagnose.h" 37 #include "sal/alloca.h" 38 #include "sal/types.h" 39 #include "typelib/typeclass.h" 40 #include "typelib/typedescription.h" 41 #include "typelib/typedescription.hxx" 42 #include "uno/any2.h" 43 #include "uno/data.h" 44 45 #include "exceptions.hxx" 46 #include "flushcode.hxx" 47 #include "fp.hxx" 48 #include "isdirectreturntype.hxx" 49 #include "vtableslotcall.hxx" 50 51 namespace { 52 53 namespace css = com::sun::star; 54 55 void loadFpRegsFromStruct(typelib_TypeDescription * type, void * data) { 56 for (typelib_CompoundTypeDescription * t = 57 reinterpret_cast< typelib_CompoundTypeDescription * >(type); 58 t != NULL; t = t->pBaseTypeDescription) 59 { 60 for (sal_Int32 i = 0; i < t->nMembers; ++i) { 61 switch (t->ppTypeRefs[i]->eTypeClass) { 62 case typelib_TypeClass_FLOAT: 63 switch (t->pMemberOffsets[i]) { 64 case 0: 65 fp_loadf0(reinterpret_cast< float * >(data)); 66 break; 67 case 4: 68 fp_loadf1(reinterpret_cast< float * >(data) + 1); 69 break; 70 case 8: 71 fp_loadf2(reinterpret_cast< float * >(data) + 2); 72 break; 73 case 12: 74 fp_loadf3(reinterpret_cast< float * >(data) + 3); 75 break; 76 case 16: 77 fp_loadf4(reinterpret_cast< float * >(data) + 4); 78 break; 79 case 20: 80 fp_loadf5(reinterpret_cast< float * >(data) + 5); 81 break; 82 case 24: 83 fp_loadf6(reinterpret_cast< float * >(data) + 6); 84 break; 85 case 28: 86 fp_loadf7(reinterpret_cast< float * >(data) + 7); 87 break; 88 default: 89 OSL_ASSERT(false); 90 break; 91 } 92 break; 93 case typelib_TypeClass_DOUBLE: 94 switch (t->pMemberOffsets[i]) { 95 case 0: 96 fp_loadd0(reinterpret_cast< double * >(data)); 97 break; 98 case 8: 99 fp_loadd2(reinterpret_cast< double * >(data) + 1); 100 break; 101 case 16: 102 fp_loadd4(reinterpret_cast< double * >(data) + 2); 103 break; 104 case 24: 105 fp_loadd6(reinterpret_cast< double * >(data) + 3); 106 break; 107 default: 108 OSL_ASSERT(false); 109 break; 110 } 111 break; 112 case typelib_TypeClass_STRUCT: 113 { 114 typelib_TypeDescription * td = NULL; 115 TYPELIB_DANGER_GET(&td, t->ppTypeRefs[i]); 116 loadFpRegsFromStruct(td, data); 117 TYPELIB_DANGER_RELEASE(td); 118 break; 119 } 120 } 121 } 122 } 123 } 124 125 void call( 126 bridges::cpp_uno::shared::CppInterfaceProxy * proxy, 127 css::uno::TypeDescription const & description, 128 bool directReturn, typelib_TypeDescriptionReference * returnType, 129 sal_Int32 count, typelib_MethodParameter * parameters, 130 unsigned long * callStack) 131 { 132 typelib_TypeDescription * rtd = NULL; 133 if (returnType != NULL) { 134 TYPELIB_DANGER_GET(&rtd, returnType); 135 } 136 bool retconv = 137 rtd != NULL && bridges::cpp_uno::shared::relatesToInterfaceType(rtd); 138 OSL_ASSERT(!(directReturn && retconv)); 139 void * retin; 140 void * retout; 141 char retbuf[32]; 142 if (directReturn) { 143 retin = returnType == NULL ? NULL : retbuf; 144 } else { 145 retout = reinterpret_cast< void * >(callStack[0]); 146 retin = retconv ? alloca(rtd->nSize) : retout; 147 } 148 void ** args = static_cast< void ** >(alloca(count * sizeof (void *))); 149 void ** cppArgs = static_cast< void ** >(alloca(count * sizeof (void *))); 150 typelib_TypeDescription ** argtds = 151 static_cast< typelib_TypeDescription ** >( 152 alloca(count * sizeof (typelib_TypeDescription *))); 153 union fp { float f; double d; }; 154 fp copies[15]; 155 sal_Int32 stackPos = directReturn ? 1 : 2; // skip return ptr and this ptr 156 for (sal_Int32 i = 0; i < count; ++i) { 157 typelib_TypeDescription * ptd = NULL; 158 TYPELIB_DANGER_GET(&ptd, parameters[i].pTypeRef); 159 if (!parameters[i].bOut && bridges::cpp_uno::shared::isSimpleType(ptd)) 160 { 161 switch (ptd->eTypeClass) { 162 case typelib_TypeClass_FLOAT: 163 if (stackPos <= 15) { 164 switch (stackPos) { 165 case 1: 166 fp_storef3(&copies[0].f); 167 break; 168 case 2: 169 fp_storef5(&copies[1].f); 170 break; 171 case 3: 172 fp_storef7(&copies[2].f); 173 break; 174 case 4: 175 fp_storef9(&copies[3].f); 176 break; 177 case 5: 178 fp_storef11(&copies[4].f); 179 break; 180 case 6: 181 fp_storef13(&copies[5].f); 182 break; 183 case 7: 184 fp_storef15(&copies[6].f); 185 break; 186 case 8: 187 fp_storef17(&copies[7].f); 188 break; 189 case 9: 190 fp_storef19(&copies[8].f); 191 break; 192 case 10: 193 fp_storef21(&copies[9].f); 194 break; 195 case 11: 196 fp_storef23(&copies[10].f); 197 break; 198 case 12: 199 fp_storef25(&copies[11].f); 200 break; 201 case 13: 202 fp_storef27(&copies[12].f); 203 break; 204 case 14: 205 fp_storef29(&copies[13].f); 206 break; 207 case 15: 208 fp_storef31(&copies[14].f); 209 break; 210 default: 211 OSL_ASSERT(false); 212 break; 213 } 214 args[i] = &copies[stackPos - 1].f; 215 } else { 216 args[i] = reinterpret_cast< char * >(callStack + stackPos) + 217 (sizeof (unsigned long) - sizeof (float)); 218 } 219 break; 220 case typelib_TypeClass_DOUBLE: 221 if (stackPos <= 15) { 222 switch (stackPos) { 223 case 1: 224 fp_stored2(&copies[0].d); 225 break; 226 case 2: 227 fp_stored4(&copies[1].d); 228 break; 229 case 3: 230 fp_stored6(&copies[2].d); 231 break; 232 case 4: 233 fp_stored8(&copies[3].d); 234 break; 235 case 5: 236 fp_stored10(&copies[4].d); 237 break; 238 case 6: 239 fp_stored12(&copies[5].d); 240 break; 241 case 7: 242 fp_stored14(&copies[6].d); 243 break; 244 case 8: 245 fp_stored16(&copies[7].d); 246 break; 247 case 9: 248 fp_stored18(&copies[8].d); 249 break; 250 case 10: 251 fp_stored20(&copies[9].d); 252 break; 253 case 11: 254 fp_stored22(&copies[10].d); 255 break; 256 case 12: 257 fp_stored24(&copies[11].d); 258 break; 259 case 13: 260 fp_stored26(&copies[12].d); 261 break; 262 case 14: 263 fp_stored28(&copies[13].d); 264 break; 265 case 15: 266 fp_stored30(&copies[14].d); 267 break; 268 default: 269 OSL_ASSERT(false); 270 break; 271 } 272 args[i] = &copies[stackPos - 1].d; 273 } else { 274 args[i] = reinterpret_cast< char * >(callStack + stackPos) + 275 (sizeof (unsigned long) - sizeof (double)); 276 } 277 break; 278 default: 279 OSL_ASSERT(ptd->nSize <= 8); 280 args[i] = reinterpret_cast< char * >(callStack + stackPos) + 281 (sizeof (unsigned long) - ptd->nSize); 282 break; 283 } 284 argtds[i] = NULL; 285 TYPELIB_DANGER_RELEASE(ptd); 286 } else { 287 cppArgs[i] = reinterpret_cast< void * >(callStack[stackPos]); 288 if (!parameters[i].bIn) { 289 args[i] = alloca(ptd->nSize); 290 argtds[i] = ptd; 291 } else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd)) { 292 args[i] = alloca(ptd->nSize); 293 uno_copyAndConvertData( 294 args[i], reinterpret_cast< void * >(callStack[stackPos]), 295 ptd, proxy->getBridge()->getCpp2Uno()); 296 argtds[i] = ptd; 297 } else { 298 args[i] = reinterpret_cast< void * >(callStack[stackPos]); 299 argtds[i] = NULL; 300 TYPELIB_DANGER_RELEASE(ptd); 301 } 302 } 303 ++stackPos; 304 } 305 uno_Any exc; 306 uno_Any * pexc = &exc; 307 proxy->getUnoI()->pDispatcher( 308 proxy->getUnoI(), description.get(), retin, args, &pexc); 309 if (pexc != NULL) { 310 for (sal_Int32 i = 0; i < count; ++i) { 311 if (argtds[i] != NULL) { 312 if (parameters[i].bIn) { 313 uno_destructData(args[i], argtds[i], NULL); 314 } 315 TYPELIB_DANGER_RELEASE(argtds[i]); 316 } 317 } 318 if (rtd != NULL) { 319 TYPELIB_DANGER_RELEASE(rtd); 320 } 321 bridges::cpp_uno::cc5_solaris_sparc64::raiseException( 322 &exc, proxy->getBridge()->getUno2Cpp()); 323 std::abort(); // just in case 324 } 325 for (sal_Int32 i = 0; i < count; ++i) { 326 if (argtds[i] != NULL) { 327 if (parameters[i].bOut) { 328 uno_destructData( 329 cppArgs[i], argtds[i], 330 reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release)); 331 uno_copyAndConvertData( 332 cppArgs[i], args[i], argtds[i], 333 proxy->getBridge()->getUno2Cpp()); 334 } 335 uno_destructData(args[i], argtds[i], NULL); 336 TYPELIB_DANGER_RELEASE(argtds[i]); 337 } 338 } 339 if (directReturn) { 340 if (rtd != NULL) { 341 switch (rtd->eTypeClass) { 342 case typelib_TypeClass_VOID: 343 break; 344 case typelib_TypeClass_BOOLEAN: 345 callStack[0] = *reinterpret_cast< sal_Bool * >(retbuf); 346 break; 347 case typelib_TypeClass_BYTE: 348 callStack[0] = *reinterpret_cast< sal_Int8 * >(retbuf); 349 break; 350 case typelib_TypeClass_SHORT: 351 callStack[0] = *reinterpret_cast< sal_Int16 * >(retbuf); 352 break; 353 case typelib_TypeClass_UNSIGNED_SHORT: 354 callStack[0] = *reinterpret_cast< sal_uInt16 * >(retbuf); 355 break; 356 case typelib_TypeClass_LONG: 357 case typelib_TypeClass_ENUM: 358 callStack[0] = *reinterpret_cast< sal_Int32 * >(retbuf); 359 break; 360 case typelib_TypeClass_UNSIGNED_LONG: 361 callStack[0] = *reinterpret_cast< sal_uInt32 * >(retbuf); 362 break; 363 case typelib_TypeClass_HYPER: 364 callStack[0] = *reinterpret_cast< sal_Int64 * >(retbuf); 365 break; 366 case typelib_TypeClass_UNSIGNED_HYPER: 367 callStack[0] = *reinterpret_cast< sal_uInt64 * >(retbuf); 368 break; 369 case typelib_TypeClass_FLOAT: 370 fp_loadf0(reinterpret_cast< float * >(retbuf)); 371 break; 372 case typelib_TypeClass_DOUBLE: 373 fp_loadd0(reinterpret_cast< double * >(retbuf)); 374 break; 375 case typelib_TypeClass_CHAR: 376 callStack[0] = *reinterpret_cast< sal_Unicode * >(retbuf); 377 break; 378 case typelib_TypeClass_STRING: 379 case typelib_TypeClass_TYPE: 380 case typelib_TypeClass_SEQUENCE: 381 case typelib_TypeClass_INTERFACE: 382 callStack[0] = reinterpret_cast< unsigned long >( 383 *reinterpret_cast< void ** >(retbuf)); 384 break; 385 case typelib_TypeClass_STRUCT: 386 loadFpRegsFromStruct(rtd, retbuf); 387 // fall through 388 case typelib_TypeClass_ANY: 389 std::memcpy(callStack, retbuf, rtd->nSize); 390 break; 391 default: 392 OSL_ASSERT(false); 393 break; 394 } 395 } 396 } else if (retconv) { 397 uno_copyAndConvertData( 398 retout, retin, rtd, proxy->getBridge()->getUno2Cpp()); 399 uno_destructData(retin, rtd, NULL); 400 } 401 if (rtd != NULL) { 402 TYPELIB_DANGER_RELEASE(rtd); 403 } 404 } 405 406 extern "C" void vtableCall( 407 sal_Int32 functionIndex, sal_Int32 vtableOffset, unsigned long * callStack) 408 { 409 bool direct = static_cast< sal_uInt32 >((functionIndex) & 0x80000000) == 0; 410 functionIndex = static_cast< sal_uInt32 >(functionIndex) & 0x7FFFFFFF; 411 bridges::cpp_uno::shared::CppInterfaceProxy * proxy 412 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( 413 reinterpret_cast< char * >(callStack[direct ? 0 : 1]) - 414 vtableOffset); 415 typelib_InterfaceTypeDescription * type = proxy->getTypeDescr(); 416 OSL_ASSERT(functionIndex < type->nMapFunctionIndexToMemberIndex); 417 sal_Int32 pos = type->pMapFunctionIndexToMemberIndex[functionIndex]; 418 css::uno::TypeDescription desc(type->ppAllMembers[pos]); 419 switch (desc.get()->eTypeClass) { 420 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 421 if (type->pMapMemberIndexToFunctionIndex[pos] == functionIndex) { 422 // Getter: 423 call( 424 proxy, desc, direct, 425 reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( 426 desc.get())->pAttributeTypeRef, 427 0, NULL, callStack); 428 } else { 429 // Setter: 430 typelib_MethodParameter param = { 431 NULL, 432 reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( 433 desc.get())->pAttributeTypeRef, 434 true, false }; 435 call(proxy, desc, true, NULL, 1, ¶m, callStack); 436 } 437 break; 438 case typelib_TypeClass_INTERFACE_METHOD: 439 switch (functionIndex) { 440 case 1: 441 proxy->acquireProxy(); 442 break; 443 case 2: 444 proxy->releaseProxy(); 445 break; 446 case 0: 447 { 448 typelib_TypeDescription * td = NULL; 449 TYPELIB_DANGER_GET( 450 &td, 451 reinterpret_cast< css::uno::Type * >( 452 callStack[2])->getTypeLibType()); 453 if (td != NULL) { 454 css::uno::XInterface * ifc = NULL; 455 proxy->getBridge()->getCppEnv()->getRegisteredInterface( 456 proxy->getBridge()->getCppEnv(), 457 reinterpret_cast< void ** >(&ifc), 458 proxy->getOid().pData, 459 reinterpret_cast< typelib_InterfaceTypeDescription * >( 460 td)); 461 if (ifc != NULL) { 462 uno_any_construct( 463 reinterpret_cast< uno_Any * >(callStack[0]), &ifc, 464 td, 465 reinterpret_cast< uno_AcquireFunc >( 466 css::uno::cpp_acquire)); 467 ifc->release(); 468 TYPELIB_DANGER_RELEASE(td); 469 break; 470 } 471 TYPELIB_DANGER_RELEASE(td); 472 } 473 } // fall through 474 default: 475 call( 476 proxy, desc, direct, 477 reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( 478 desc.get())->pReturnTypeRef, 479 reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( 480 desc.get())->nParams, 481 reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( 482 desc.get())->pParams, 483 callStack); 484 } 485 break; 486 default: 487 OSL_ASSERT(false); 488 break; 489 } 490 } 491 492 int const codeSnippetSize = 10 * 4; 493 494 unsigned char * generateCodeSnippet( 495 unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, 496 bool directReturn) 497 { 498 sal_uInt32 index = functionIndex; 499 if (!directReturn) { 500 index |= 0x80000000; 501 } 502 unsigned int * p = reinterpret_cast< unsigned int * >(code); 503 OSL_ASSERT(sizeof (unsigned int) == 4); 504 // 0*4: save %sp, -176, %sp ! minimal stack frame: 505 *p++ = 0x9DE3BF50; 506 // 1*4: rd %pc, %l0: 507 *p++ = 0xA1414000; 508 // 2*4: ldx %l0, (8-1)*4, %l0: 509 *p++ = 0xE05C201C; 510 // 3*4: sethi %hi(index), %o0: 511 *p++ = 0x11000000 | (index >> 10); 512 // 4*4: or %o0, %lo(index), %o0: 513 *p++ = 0x90122000 | (index & 0x3FF); 514 // 5*4: sethi %hi(vtableOffset), %o1: 515 *p++ = 0x13000000 | (vtableOffset >> 10); 516 // 6*4: jmpl %l0, %g0, %g0: 517 *p++ = 0x81C40000; 518 // 7*4: or %o1, %lo(vtableOffset), %o1: 519 *p++ = 0x92126000 | (vtableOffset & 0x3FF); 520 // 8*4: .xword privateSnippetExecutor: 521 *reinterpret_cast< unsigned long * >(p) = 522 reinterpret_cast< unsigned long >(vtableSlotCall); 523 return code + codeSnippetSize; 524 } 525 526 } 527 528 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; 529 530 bridges::cpp_uno::shared::VtableFactory::Slot * 531 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) { 532 return static_cast< Slot * >(block) + 1; 533 } 534 535 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( 536 sal_Int32 slotCount) 537 { 538 return (slotCount + 3) * sizeof (Slot) + slotCount * codeSnippetSize; 539 } 540 541 bridges::cpp_uno::shared::VtableFactory::Slot * 542 bridges::cpp_uno::shared::VtableFactory::initializeBlock( 543 void * block, sal_Int32 slotCount) 544 { 545 Slot * slots = mapBlockToVtable(block) + 2; 546 slots[-3].fn = NULL; // RTTI 547 slots[-2].fn = NULL; // null 548 slots[-1].fn = NULL; // destructor 549 return slots + slotCount; 550 } 551 552 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( 553 Slot ** slots, unsigned char * code, 554 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, 555 sal_Int32 functionCount, sal_Int32 vtableOffset) 556 { 557 (*slots) -= functionCount; 558 Slot * s = *slots; 559 for (sal_Int32 i = 0; i < type->nMembers; ++i) { 560 typelib_TypeDescription * member = 0; 561 TYPELIB_DANGER_GET(&member, type->ppMembers[i]); 562 OSL_ASSERT(member != 0); 563 switch (member->eTypeClass) { 564 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 565 // Getter: 566 (s++)->fn = code; 567 code = generateCodeSnippet( 568 code, functionOffset++, vtableOffset, 569 bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType( 570 reinterpret_cast< 571 typelib_InterfaceAttributeTypeDescription * >( 572 member)->pAttributeTypeRef)); 573 // Setter: 574 if (!reinterpret_cast< 575 typelib_InterfaceAttributeTypeDescription * >( 576 member)->bReadOnly) 577 { 578 (s++)->fn = code; 579 code = generateCodeSnippet( 580 code, functionOffset++, vtableOffset, true); 581 } 582 break; 583 584 case typelib_TypeClass_INTERFACE_METHOD: 585 (s++)->fn = code; 586 code = generateCodeSnippet( 587 code, functionOffset++, vtableOffset, 588 bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType( 589 reinterpret_cast< 590 typelib_InterfaceMethodTypeDescription * >( 591 member)->pReturnTypeRef)); 592 break; 593 594 default: 595 OSL_ASSERT(false); 596 break; 597 } 598 TYPELIB_DANGER_RELEASE(member); 599 } 600 return code; 601 } 602 603 void bridges::cpp_uno::shared::VtableFactory::flushCode( 604 unsigned char const * begin, unsigned char const * end) 605 { 606 bridges::cpp_uno::cc5_solaris_sparc64::flushCode(begin, end); 607 } 608