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 <com/sun/star/uno/genfunc.hxx>
28 #include <uno/data.h>
29 #include <typelib/typedescription.hxx>
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
36 #include "share.hxx"
37 #include <stdio.h>
38 #include <string.h>
39
40
41 using namespace ::com::sun::star::uno;
42
43 namespace
44 {
45
46 //==================================================================================================
cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy * pThis,const typelib_TypeDescription * pMemberTypeDescr,typelib_TypeDescriptionReference * pReturnTypeRef,sal_Int32 nParams,typelib_MethodParameter * pParams,void ** gpreg,void ** fpreg,void ** ovrflw,sal_Int64 * pRegisterReturn)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 ** gpreg, void ** fpreg, void ** ovrflw,
53 sal_Int64 * pRegisterReturn /* space for register return */ )
54 {
55 #ifdef CMC_DEBUG
56 fprintf(stderr, "as far as cpp2uno_call\n");
57 #endif
58
59 int ng = 0; //number of gpr registers used
60 int nf = 0; //number of fpr regsiters used
61
62 // gpreg: [ret *], this, [gpr params]
63 // fpreg: [fpr params]
64 // ovrflw: [gpr or fpr params (properly aligned)]
65
66 // return
67 typelib_TypeDescription * pReturnTypeDescr = 0;
68 if (pReturnTypeRef)
69 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
70
71 void * pUnoReturn = 0;
72 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
73
74 if (pReturnTypeDescr)
75 {
76 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
77 {
78 pUnoReturn = pRegisterReturn; // direct way for simple types
79 }
80 else // complex return via ptr (pCppReturn)
81 {
82 pCppReturn = *(void **)gpreg;
83 gpreg++;
84 ng++;
85
86 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
87 ? alloca( pReturnTypeDescr->nSize )
88 : pCppReturn); // direct way
89 }
90 }
91 // pop this
92 gpreg++;
93 ng++;
94
95 // stack space
96 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int64), "### unexpected size!" );
97 // parameters
98 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
99 void ** pCppArgs = pUnoArgs + nParams;
100 // indizes of values this have to be converted (interface conversion cpp<=>uno)
101 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
102 // type descriptions for reconversions
103 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
104
105 sal_Int32 nTempIndizes = 0;
106 bool bOverFlowUsed = false;
107 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
108 {
109 const typelib_MethodParameter & rParam = pParams[nPos];
110 typelib_TypeDescription * pParamTypeDescr = 0;
111 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
112
113 #ifdef CMC_DEBUG
114 fprintf(stderr, "arg %d of %d\n", nPos, nParams);
115 #endif
116
117 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
118 {
119 #ifdef CMC_DEBUG
120 fprintf(stderr, "simple\n");
121 #endif
122
123 switch (pParamTypeDescr->eTypeClass)
124 {
125 case typelib_TypeClass_FLOAT:
126 case typelib_TypeClass_DOUBLE:
127 if (nf < ppc64::MAX_SSE_REGS)
128 {
129 if (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT)
130 {
131 float tmp = (float) (*((double *)fpreg));
132 (*((float *) fpreg)) = tmp;
133 }
134 pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++;
135 nf++;
136 }
137 else
138 {
139 pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw;
140 bOverFlowUsed = true;
141 }
142 if (bOverFlowUsed) ovrflw++;
143 break;
144 case typelib_TypeClass_BYTE:
145 case typelib_TypeClass_BOOLEAN:
146 if (ng < ppc64::MAX_GPR_REGS)
147 {
148 pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)gpreg) + (sizeof(void*)-1));
149 ng++;
150 gpreg++;
151 }
152 else
153 {
154 pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)ovrflw) + (sizeof(void*)-1));
155 bOverFlowUsed = true;
156 }
157 if (bOverFlowUsed) ovrflw++;
158 break;
159 case typelib_TypeClass_CHAR:
160 case typelib_TypeClass_SHORT:
161 case typelib_TypeClass_UNSIGNED_SHORT:
162 if (ng < ppc64::MAX_GPR_REGS)
163 {
164 pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)gpreg) + (sizeof(void*)-2));
165 ng++;
166 gpreg++;
167 }
168 else
169 {
170 pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)ovrflw) + (sizeof(void*)-2));
171 bOverFlowUsed = true;
172 }
173 if (bOverFlowUsed) ovrflw++;
174 break;
175 case typelib_TypeClass_ENUM:
176 case typelib_TypeClass_LONG:
177 case typelib_TypeClass_UNSIGNED_LONG:
178 if (ng < ppc64::MAX_GPR_REGS)
179 {
180 pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)gpreg) + (sizeof(void*)-4));
181 ng++;
182 gpreg++;
183 }
184 else
185 {
186 pCppArgs[nPos] = pUnoArgs[nPos] = (((char *)ovrflw) + (sizeof(void*)-4));
187 bOverFlowUsed = true;
188 }
189 if (bOverFlowUsed) ovrflw++;
190 break;
191 default:
192 if (ng < ppc64::MAX_GPR_REGS)
193 {
194 pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++;
195 ng++;
196 }
197 else
198 {
199 pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw;
200 bOverFlowUsed = true;
201 }
202 if (bOverFlowUsed) ovrflw++;
203 break;
204 }
205
206 // no longer needed
207 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
208 }
209 else // ptr to complex value | ref
210 {
211 #ifdef CMC_DEBUG
212 fprintf(stderr, "complex, ng is %d\n", ng);
213 #endif
214 void *pCppStack; //temporary stack pointer
215
216 if (ng < ppc64::MAX_GPR_REGS)
217 {
218 pCppArgs[nPos] = pCppStack = *gpreg++;
219 ng++;
220 }
221 else
222 {
223 pCppArgs[nPos] = pCppStack = *ovrflw;
224 bOverFlowUsed = true;
225 }
226 if (bOverFlowUsed) ovrflw++;
227
228 if (! rParam.bIn) // is pure out
229 {
230 // uno out is unconstructed mem!
231 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
232 pTempIndizes[nTempIndizes] = nPos;
233 // will be released at reconversion
234 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
235 }
236 // is in/inout
237 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
238 {
239 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
240 pCppStack, pParamTypeDescr,
241 pThis->getBridge()->getCpp2Uno() );
242 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
243 // will be released at reconversion
244 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
245 }
246 else // direct way
247 {
248 pUnoArgs[nPos] = pCppStack;
249 // no longer needed
250 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
251 }
252 }
253 }
254
255 #ifdef CMC_DEBUG
256 fprintf(stderr, "end of params\n");
257 #endif
258
259 // ExceptionHolder
260 uno_Any aUnoExc; // Any will be constructed by callee
261 uno_Any * pUnoExc = &aUnoExc;
262
263 // invoke uno dispatch call
264 (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
265
266 // in case an exception occurred...
267 if (pUnoExc)
268 {
269 // destruct temporary in/inout params
270 for ( ; nTempIndizes--; )
271 {
272 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
273
274 if (pParams[nIndex].bIn) // is in/inout => was constructed
275 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
276 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
277 }
278 if (pReturnTypeDescr)
279 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
280
281 CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() );
282 // has to destruct the any
283 // is here for dummy
284 return typelib_TypeClass_VOID;
285 }
286 else // else no exception occurred...
287 {
288 // temporary params
289 for ( ; nTempIndizes--; )
290 {
291 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
292 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
293
294 if (pParams[nIndex].bOut) // inout/out
295 {
296 // convert and assign
297 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
298 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
299 pThis->getBridge()->getUno2Cpp() );
300 }
301 // destroy temp uno param
302 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
303
304 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
305 }
306 // return
307 if (pCppReturn) // has complex return
308 {
309 if (pUnoReturn != pCppReturn) // needs reconversion
310 {
311 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
312 pThis->getBridge()->getUno2Cpp() );
313 // destroy temp uno return
314 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
315 }
316 // complex return ptr is set to return reg
317 *(void **)pRegisterReturn = pCppReturn;
318 }
319 if (pReturnTypeDescr)
320 {
321 typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
322 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
323 return eRet;
324 }
325 else
326 return typelib_TypeClass_VOID;
327 }
328 }
329
330
331 //==================================================================================================
cpp_mediate(sal_uInt64 nOffsetAndIndex,void ** gpreg,void ** fpreg,long sp,sal_Int64 * pRegisterReturn)332 static typelib_TypeClass cpp_mediate(
333 sal_uInt64 nOffsetAndIndex,
334 void ** gpreg, void ** fpreg, long sp,
335 sal_Int64 * pRegisterReturn /* space for register return */ )
336 {
337 OSL_ENSURE( sizeof(sal_Int64)==sizeof(void *), "### unexpected!" );
338
339 sal_Int32 nVtableOffset = (nOffsetAndIndex >> 32);
340 sal_Int32 nFunctionIndex = (nOffsetAndIndex & 0xFFFFFFFF);
341
342 long sf = *(long*)sp;
343 void ** ovrflw = (void**)(sf + 112);
344
345 // gpreg: [ret *], this, [other gpr params]
346 // fpreg: [fpr params]
347 // ovrflw: [gpr or fpr params (properly aligned)]
348
349 void * pThis;
350 if (nFunctionIndex & 0x80000000 )
351 {
352 nFunctionIndex &= 0x7fffffff;
353 pThis = gpreg[1];
354 #ifdef CMC_DEBUG
355 fprintf(stderr, "pThis is gpreg[1]\n");
356 #endif
357 }
358 else
359 {
360 pThis = gpreg[0];
361 #ifdef CMC_DEBUG
362 fprintf(stderr, "pThis is gpreg[0]\n");
363 #endif
364 }
365
366 #ifdef CMC_DEBUG
367 fprintf(stderr, "pThis is %lx\n", pThis);
368 #endif
369
370 pThis = static_cast< char * >(pThis) - nVtableOffset;
371
372 #ifdef CMC_DEBUG
373 fprintf(stderr, "pThis is now %lx\n", pThis);
374 #endif
375
376 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
377 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
378 pThis);
379
380 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
381
382 #ifdef CMC_DEBUG
383 fprintf(stderr, "indexes are %d %d\n", nFunctionIndex, pTypeDescr->nMapFunctionIndexToMemberIndex);
384 #endif
385
386 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
387 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
388 {
389 throw RuntimeException(
390 rtl::OUString::createFromAscii("illegal vtable index!"),
391 (XInterface *)pThis );
392 }
393
394 // determine called method
395 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
396 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
397
398 #ifdef CMC_DEBUG
399 fprintf(stderr, "members are %d %d\n", nMemberPos, pTypeDescr->nAllMembers);
400 #endif
401
402 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
403
404 typelib_TypeClass eRet;
405 switch (aMemberDescr.get()->eTypeClass)
406 {
407 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
408 {
409 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
410 {
411 // is GET method
412 eRet = cpp2uno_call(
413 pCppI, aMemberDescr.get(),
414 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
415 0, 0, // no params
416 gpreg, fpreg, ovrflw, pRegisterReturn );
417 }
418 else
419 {
420 // is SET method
421 typelib_MethodParameter aParam;
422 aParam.pTypeRef =
423 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
424 aParam.bIn = sal_True;
425 aParam.bOut = sal_False;
426
427 eRet = cpp2uno_call(
428 pCppI, aMemberDescr.get(),
429 0, // indicates void return
430 1, &aParam,
431 gpreg, fpreg, ovrflw, pRegisterReturn );
432 }
433 break;
434 }
435 case typelib_TypeClass_INTERFACE_METHOD:
436 {
437 // is METHOD
438 switch (nFunctionIndex)
439 {
440 case 1: // acquire()
441 pCppI->acquireProxy(); // non virtual call!
442 eRet = typelib_TypeClass_VOID;
443 break;
444 case 2: // release()
445 pCppI->releaseProxy(); // non virtual call!
446 eRet = typelib_TypeClass_VOID;
447 break;
448 case 0: // queryInterface() opt
449 {
450 typelib_TypeDescription * pTD = 0;
451 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() );
452 if (pTD)
453 {
454 XInterface * pInterface = 0;
455 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
456 pCppI->getBridge()->getCppEnv(),
457 (void **)&pInterface, pCppI->getOid().pData,
458 (typelib_InterfaceTypeDescription *)pTD );
459
460 if (pInterface)
461 {
462 ::uno_any_construct(
463 reinterpret_cast< uno_Any * >( gpreg[0] ),
464 &pInterface, pTD, cpp_acquire );
465 pInterface->release();
466 TYPELIB_DANGER_RELEASE( pTD );
467 *(void **)pRegisterReturn = gpreg[0];
468 eRet = typelib_TypeClass_ANY;
469 break;
470 }
471 TYPELIB_DANGER_RELEASE( pTD );
472 }
473 } // else perform queryInterface()
474 default:
475 eRet = cpp2uno_call(
476 pCppI, aMemberDescr.get(),
477 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
478 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
479 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
480 gpreg, fpreg, ovrflw, pRegisterReturn );
481 }
482 break;
483 }
484 default:
485 {
486 #ifdef CMC_DEBUG
487 fprintf(stderr, "screwed\n");
488 #endif
489
490 throw RuntimeException(
491 rtl::OUString::createFromAscii("no member description found!"),
492 (XInterface *)pThis );
493 // is here for dummy
494 eRet = typelib_TypeClass_VOID;
495 }
496 }
497
498 #ifdef CMC_DEBUG
499 fprintf(stderr, "end of cpp_mediate\n");
500 #endif
501 return eRet;
502 }
503
privateSnippetExecutor(...)504 extern "C" void privateSnippetExecutor( ... )
505 {
506 volatile long nOffsetAndIndex;
507
508 //mr %r3, %r11 # move into arg1 the 64bit value passed from OOo
509 __asm__ __volatile__ (
510 "mr %0, 11\n\t"
511 : "=r" (nOffsetAndIndex) : );
512
513 sal_uInt64 gpreg[ppc64::MAX_GPR_REGS];
514 double fpreg[ppc64::MAX_SSE_REGS];
515
516 __asm__ __volatile__ (
517 "std 3, 0(%0)\t\n"
518 "std 4, 8(%0)\t\n"
519 "std 5, 16(%0)\t\n"
520 "std 6, 24(%0)\t\n"
521 "std 7, 32(%0)\t\n"
522 "std 8, 40(%0)\t\n"
523 "std 9, 48(%0)\t\n"
524 "std 10, 56(%0)\t\n"
525 "stfd 1, 0(%1)\t\n"
526 "stfd 2, 8(%1)\t\n"
527 "stfd 3, 16(%1)\t\n"
528 "stfd 4, 24(%1)\t\n"
529 "stfd 5, 32(%1)\t\n"
530 "stfd 6, 40(%1)\t\n"
531 "stfd 7, 48(%1)\t\n"
532 "stfd 8, 56(%1)\t\n"
533 "stfd 9, 64(%1)\t\n"
534 "stfd 10, 72(%1)\t\n"
535 "stfd 11, 80(%1)\t\n"
536 "stfd 12, 88(%1)\t\n"
537 "stfd 13, 96(%1)\t\n"
538 : : "r" (gpreg), "r" (fpreg)
539 : "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
540 "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7", "fr8", "fr9",
541 "fr10", "fr11", "fr12", "fr13"
542 );
543
544 volatile long sp;
545
546 //stack pointer
547 __asm__ __volatile__ (
548 "mr %0, 1\n\t"
549 : "=r" (sp) : );
550
551 volatile long nRegReturn[1];
552
553 typelib_TypeClass aType =
554 cpp_mediate( nOffsetAndIndex, (void**)gpreg, (void**)fpreg, sp, (sal_Int64*)nRegReturn);
555
556 switch( aType )
557 {
558 case typelib_TypeClass_VOID:
559 break;
560 case typelib_TypeClass_BOOLEAN:
561 case typelib_TypeClass_BYTE:
562 __asm__( "lbz 3,%0\n\t"
563 : : "m" (nRegReturn[0]) );
564 break;
565 case typelib_TypeClass_CHAR:
566 case typelib_TypeClass_UNSIGNED_SHORT:
567 __asm__( "lhz 3,%0\n\t"
568 : : "m" (nRegReturn[0]) );
569 break;
570 case typelib_TypeClass_SHORT:
571 __asm__( "lha 3,%0\n\t"
572 : : "m" (nRegReturn[0]) );
573 break;
574 case typelib_TypeClass_ENUM:
575 case typelib_TypeClass_UNSIGNED_LONG:
576 __asm__( "lwz 3,%0\n\t"
577 : : "m"(nRegReturn[0]) );
578 break;
579 case typelib_TypeClass_LONG:
580 __asm__( "lwa 3,%0\n\t"
581 : : "m"(nRegReturn[0]) );
582 break;
583 case typelib_TypeClass_FLOAT:
584 __asm__( "lfs 1,%0\n\t"
585 : : "m" (*((float*)nRegReturn)) );
586 break;
587 case typelib_TypeClass_DOUBLE:
588 __asm__( "lfd 1,%0\n\t"
589 : : "m" (*((double*)nRegReturn)) );
590 break;
591 default:
592 __asm__( "ld 3,%0\n\t"
593 : : "m" (nRegReturn[0]) );
594 break;
595 }
596 }
597
598 const int codeSnippetSize = 24;
599
codeSnippet(unsigned char * code,sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,bool simpleRetType)600 unsigned char * codeSnippet( unsigned char * code, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
601 bool simpleRetType)
602 {
603 #ifdef CMC_DEBUG
604 fprintf(stderr,"in codeSnippet functionIndex is %x\n", nFunctionIndex);
605 fprintf(stderr,"in codeSnippet vtableOffset is %x\n", nVtableOffset);
606 #endif
607
608 sal_uInt64 nOffsetAndIndex = ( ( (sal_uInt64) nVtableOffset ) << 32 ) | ( (sal_uInt64) nFunctionIndex );
609
610 if ( !simpleRetType )
611 nOffsetAndIndex |= 0x80000000;
612
613 void ** raw = (void **)&code[0];
614 memcpy(raw, (char*) privateSnippetExecutor, 16);
615 raw[2] = (void*) nOffsetAndIndex;
616 #ifdef CMC_DEBUG
617 fprintf(stderr, "in: offset/index is %x %x %d, %lx\n",
618 nFunctionIndex, nVtableOffset, !simpleRetType, raw[2]);
619 #endif
620 return (code + codeSnippetSize);
621 }
622
623 }
624
flushCode(unsigned char const * bptr,unsigned char const * eptr)625 void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * bptr, unsigned char const * eptr)
626 {
627 int const lineSize = 32;
628 for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) {
629 __asm__ volatile ("dcbst 0, %0" : : "r"(p) : "memory");
630 }
631 __asm__ volatile ("sync" : : : "memory");
632 for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) {
633 __asm__ volatile ("icbi 0, %0" : : "r"(p) : "memory");
634 }
635 __asm__ volatile ("isync" : : : "memory");
636 }
637
638 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
639
640 bridges::cpp_uno::shared::VtableFactory::Slot *
mapBlockToVtable(void * block)641 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
642 {
643 return static_cast< Slot * >(block) + 2;
644 }
645
getBlockSize(sal_Int32 slotCount)646 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
647 sal_Int32 slotCount)
648 {
649 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
650 }
651
652 bridges::cpp_uno::shared::VtableFactory::Slot *
initializeBlock(void * block,sal_Int32 slotCount)653 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
654 void * block, sal_Int32 slotCount)
655 {
656 Slot * slots = mapBlockToVtable(block);
657 slots[-2].fn = 0;
658 slots[-1].fn = 0;
659 return slots + slotCount;
660 }
661
addLocalFunctions(Slot ** slots,unsigned char * code,sal_PtrDiff writetoexecdiff,typelib_InterfaceTypeDescription const * type,sal_Int32 functionOffset,sal_Int32 functionCount,sal_Int32 vtableOffset)662 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
663 Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff,
664 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
665 sal_Int32 functionCount, sal_Int32 vtableOffset)
666 {
667 (*slots) -= functionCount;
668 Slot * s = *slots;
669 #ifdef CMC_DEBUG
670 fprintf(stderr, "in addLocalFunctions functionOffset is %x\n",functionOffset);
671 fprintf(stderr, "in addLocalFunctions vtableOffset is %x\n",vtableOffset);
672 #endif
673
674 for (sal_Int32 i = 0; i < type->nMembers; ++i) {
675 typelib_TypeDescription * member = 0;
676 TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
677 OSL_ASSERT(member != 0);
678 switch (member->eTypeClass) {
679 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
680 // Getter:
681 (s++)->fn = code + writetoexecdiff;
682 code = codeSnippet(
683 code, functionOffset++, vtableOffset,
684 bridges::cpp_uno::shared::isSimpleType(
685 reinterpret_cast<
686 typelib_InterfaceAttributeTypeDescription * >(
687 member)->pAttributeTypeRef));
688
689 // Setter:
690 if (!reinterpret_cast<
691 typelib_InterfaceAttributeTypeDescription * >(
692 member)->bReadOnly)
693 {
694 (s++)->fn = code + writetoexecdiff;
695 code = codeSnippet(code, functionOffset++, vtableOffset, true);
696 }
697 break;
698
699 case typelib_TypeClass_INTERFACE_METHOD:
700 (s++)->fn = code + writetoexecdiff;
701 code = codeSnippet(
702 code, functionOffset++, vtableOffset,
703 bridges::cpp_uno::shared::isSimpleType(
704 reinterpret_cast<
705 typelib_InterfaceMethodTypeDescription * >(
706 member)->pReturnTypeRef));
707 break;
708
709 default:
710 OSL_ASSERT(false);
711 break;
712 }
713 TYPELIB_DANGER_RELEASE(member);
714 }
715 return code;
716 }
717
718 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
719