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
38 using namespace ::com::sun::star::uno;
39
40 namespace
41 {
42
43 //==================================================================================================
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)44 static typelib_TypeClass cpp2uno_call(
45 bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
46 const typelib_TypeDescription * pMemberTypeDescr,
47 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
48 sal_Int32 nParams, typelib_MethodParameter * pParams,
49 void ** gpreg, void ** fpreg, void ** ovrflw,
50 sal_Int64 * pRegisterReturn /* space for register return */ )
51 {
52
53 // gpreg: [ret *], this, [gpr params]
54 // fpreg: [fpr params]
55 // ovrflw: [gpr or fpr params (space for entire parameter list in structure format properly aligned)]
56
57 // return
58 typelib_TypeDescription * pReturnTypeDescr = 0;
59 if (pReturnTypeRef)
60 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
61
62 void * pUnoReturn = 0;
63 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
64
65 sal_Int32 ngpreg = 0;
66 sal_Int32 nfpreg = 0;
67
68
69 if (pReturnTypeDescr)
70 {
71 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
72 pUnoReturn = pRegisterReturn; // direct way for simple types
73 else // complex return via ptr (pCppReturn)
74 {
75 pCppReturn = *gpreg;
76 ngpreg++;
77 ++ovrflw;
78
79 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
80 ? alloca( pReturnTypeDescr->nSize )
81 : pCppReturn); // direct way
82 }
83 }
84 // pop this
85 ngpreg++;
86 ++ovrflw;
87
88 // after handling optional return pointer and "this"
89 // make use of the space that is allocated to store all parameters in the callers stack
90 // by comying the proper registers filled with parameters to that space
91 char * pCppStack = (char *)ovrflw;
92
93
94 sal_Int32 nPos;
95
96 for ( nPos = 0; nPos < nParams; ++nPos )
97 {
98 const typelib_MethodParameter & rParam = pParams[nPos];
99 if (rParam.bOut)
100 {
101 if (ngpreg < 8)
102 {
103 *(sal_Int32 *)pCppStack = ((sal_Int32 *)gpreg)[ngpreg++];
104 }
105 pCppStack += sizeof (sal_Int32);
106 }
107 else
108 {
109 switch (rParam.pTypeRef->eTypeClass)
110 {
111 case typelib_TypeClass_FLOAT:
112 if (nfpreg < 13)
113 {
114 *(float *)pCppStack = ((double *)fpreg)[nfpreg++];
115 }
116 pCppStack += sizeof (float);
117 ngpreg += 1;
118 break;
119 case typelib_TypeClass_DOUBLE:
120 if (nfpreg < 13)
121 {
122 *(double *)pCppStack = ((double *)fpreg)[nfpreg++];
123 }
124 pCppStack += sizeof (double);
125 ngpreg += 2;
126 break;
127 case typelib_TypeClass_UNSIGNED_HYPER:
128 case typelib_TypeClass_HYPER:
129 if (ngpreg < 8)
130 {
131 *(sal_Int32 *)pCppStack = ((sal_Int32 *)gpreg)[ngpreg++];
132 }
133 pCppStack += sizeof (sal_Int32);
134 // fall through on purpose
135 default:
136 if (ngpreg < 8)
137 {
138 *(sal_Int32 *)pCppStack = ((sal_Int32 *)gpreg)[ngpreg++];
139 }
140 pCppStack += sizeof (sal_Int32);
141 }
142 }
143 }
144
145 // now the stack has all of the paramters stored in it ready to be processed
146 // so we are ready to build the uno call stack
147 pCppStack = (char *)ovrflw;
148
149 // stack space
150 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
151
152 // parameters
153 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
154 void ** pCppArgs = pUnoArgs + nParams;
155
156 // indizes of values this have to be converted (interface conversion cpp<=>uno)
157 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
158
159 // type descriptions for reconversions
160 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
161
162 sal_Int32 nTempIndizes = 0;
163
164 for ( nPos = 0; nPos < nParams; ++nPos )
165 {
166 const typelib_MethodParameter & rParam = pParams[nPos];
167 typelib_TypeDescription * pParamTypeDescr = 0;
168 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
169
170 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
171 // value
172 {
173 switch (pParamTypeDescr->eTypeClass)
174 {
175 case typelib_TypeClass_BOOLEAN:
176 case typelib_TypeClass_BYTE:
177 pCppArgs[nPos] = pCppStack +3;
178 pUnoArgs[nPos] = pCppStack +3;
179 break;
180 case typelib_TypeClass_CHAR:
181 case typelib_TypeClass_SHORT:
182 case typelib_TypeClass_UNSIGNED_SHORT:
183 pCppArgs[nPos] = pCppStack +2;
184 pUnoArgs[nPos] = pCppStack +2;
185 break;
186 case typelib_TypeClass_HYPER:
187 case typelib_TypeClass_UNSIGNED_HYPER:
188 case typelib_TypeClass_DOUBLE:
189 pCppArgs[nPos] = pCppStack;
190 pUnoArgs[nPos] = pCppStack;
191 pCppStack += sizeof(sal_Int32); // extra long (two regs)
192 break;
193 default:
194 pCppArgs[nPos] = pCppStack;
195 pUnoArgs[nPos] = pCppStack;
196 }
197 // no longer needed
198 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
199 }
200 else // ptr to complex value | ref
201 {
202 pCppArgs[nPos] = *(void **)pCppStack;
203
204 if (! rParam.bIn) // is pure out
205 {
206 // uno out is unconstructed mem!
207 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
208 pTempIndizes[nTempIndizes] = nPos;
209 // will be released at reconversion
210 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
211 }
212 // is in/inout
213 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
214 {
215 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
216 *(void **)pCppStack, pParamTypeDescr,
217 pThis->getBridge()->getCpp2Uno() );
218 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
219 // will be released at reconversion
220 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
221 }
222 else // direct way
223 {
224 pUnoArgs[nPos] = *(void **)pCppStack;
225 // no longer needed
226 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
227 }
228 }
229 pCppStack += sizeof(sal_Int32); // standard parameter length
230 }
231
232
233 // ExceptionHolder
234 uno_Any aUnoExc; // Any will be constructed by callee
235 uno_Any * pUnoExc = &aUnoExc;
236
237 // invoke uno dispatch call
238 (*pThis->getUnoI()->pDispatcher)(
239 pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
240
241 // in case an exception occured...
242 if (pUnoExc)
243 {
244 // destruct temporary in/inout params
245 for ( ; nTempIndizes--; )
246 {
247 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
248
249 if (pParams[nIndex].bIn) // is in/inout => was constructed
250 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
251 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
252 }
253 if (pReturnTypeDescr)
254 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
255
256 CPPU_CURRENT_NAMESPACE::raiseException(
257 &aUnoExc, pThis->getBridge()->getUno2Cpp() );
258 // has to destruct the any
259 // is here for dummy
260 return typelib_TypeClass_VOID;
261 }
262 else // else no exception occured...
263 {
264 // temporary params
265 for ( ; nTempIndizes--; )
266 {
267 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
268 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
269
270 if (pParams[nIndex].bOut) // inout/out
271 {
272 // convert and assign
273 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
274 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
275 pThis->getBridge()->getUno2Cpp() );
276 }
277 // destroy temp uno param
278 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
279
280 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
281 }
282 // return
283 if (pCppReturn) // has complex return
284 {
285 if (pUnoReturn != pCppReturn) // needs reconversion
286 {
287 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
288 pThis->getBridge()->getUno2Cpp() );
289 // destroy temp uno return
290 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
291 }
292 // complex return ptr is set to return reg
293 *(void **)pRegisterReturn = pCppReturn;
294 }
295 if (pReturnTypeDescr)
296 {
297 typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
298 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
299 return eRet;
300 }
301 else
302 return typelib_TypeClass_VOID;
303 }
304 }
305
306
307 //==================================================================================================
cpp_mediate(sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,void ** gpreg,void ** fpreg,void ** ovrflw,sal_Int64 * pRegisterReturn)308 static typelib_TypeClass cpp_mediate(
309 sal_Int32 nFunctionIndex,
310 sal_Int32 nVtableOffset,
311 void ** gpreg, void ** fpreg, void ** ovrflw,
312 sal_Int64 * pRegisterReturn /* space for register return */ )
313 {
314 OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
315
316 // gpreg: [ret *], this, [other gpr params]
317 // fpreg: [fpr params]
318 // ovrflw: [gpr or fpr params (in space allocated for all params properly aligned)]
319
320 void * pThis;
321 if( nFunctionIndex & 0x80000000 )
322 {
323 nFunctionIndex &= 0x7fffffff;
324 pThis = gpreg[1];
325 }
326 else
327 {
328 pThis = gpreg[0];
329 }
330
331 pThis = static_cast< char * >(pThis) - nVtableOffset;
332 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
333 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(pThis);
334
335
336 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
337
338 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
339 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
340 {
341 throw RuntimeException(
342 rtl::OUString::createFromAscii("illegal vtable index!"),
343 (XInterface *)pThis );
344 }
345
346 // determine called method
347 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
348 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
349
350 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
351
352 typelib_TypeClass eRet;
353 switch (aMemberDescr.get()->eTypeClass)
354 {
355 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
356 {
357 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
358 {
359 // is GET method
360 eRet = cpp2uno_call(
361 pCppI, aMemberDescr.get(),
362 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
363 0, 0, // no params
364 gpreg, fpreg, ovrflw, pRegisterReturn );
365 }
366 else
367 {
368 // is SET method
369 typelib_MethodParameter aParam;
370 aParam.pTypeRef =
371 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
372 aParam.bIn = sal_True;
373 aParam.bOut = sal_False;
374
375 eRet = cpp2uno_call(
376 pCppI, aMemberDescr.get(),
377 0, // indicates void return
378 1, &aParam,
379 gpreg, fpreg, ovrflw, pRegisterReturn );
380 }
381 break;
382 }
383 case typelib_TypeClass_INTERFACE_METHOD:
384 {
385 // is METHOD
386 switch (nFunctionIndex)
387 {
388 case 1: // acquire()
389 pCppI->acquireProxy(); // non virtual call!
390 eRet = typelib_TypeClass_VOID;
391 break;
392 case 2: // release()
393 pCppI->releaseProxy(); // non virtual call!
394 eRet = typelib_TypeClass_VOID;
395 break;
396 case 0: // queryInterface() opt
397 {
398 typelib_TypeDescription * pTD = 0;
399 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() );
400 if (pTD)
401 {
402 XInterface * pInterface = 0;
403 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
404 pCppI->getBridge()->getCppEnv(),
405 (void **)&pInterface, pCppI->getOid().pData, (typelib_InterfaceTypeDescription *)pTD );
406
407 if (pInterface)
408 {
409 ::uno_any_construct(
410 reinterpret_cast< uno_Any * >( gpreg[0] ),
411 &pInterface, pTD, cpp_acquire );
412 pInterface->release();
413 TYPELIB_DANGER_RELEASE( pTD );
414 *(void **)pRegisterReturn = gpreg[0];
415 eRet = typelib_TypeClass_ANY;
416 break;
417 }
418 TYPELIB_DANGER_RELEASE( pTD );
419 }
420 } // else perform queryInterface()
421 default:
422 eRet = cpp2uno_call(
423 pCppI, aMemberDescr.get(),
424 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
425 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
426 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
427 gpreg, fpreg, ovrflw, pRegisterReturn );
428 }
429 break;
430 }
431 default:
432 {
433 throw RuntimeException(
434 rtl::OUString::createFromAscii("no member description found!"),
435 (XInterface *)pThis );
436 // is here for dummy
437 eRet = typelib_TypeClass_VOID;
438 }
439 }
440
441 return eRet;
442 }
443
444 //==================================================================================================
445 /**
446 * is called on incoming vtable calls
447 * (called by asm snippets)
448 */
cpp_vtable_call(int nFunctionIndex,int nVtableOffset,void ** gpregptr,void ** fpregptr,void ** ovrflw)449 static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** fpregptr, void** ovrflw)
450 {
451 sal_Int32 gpreg[8];
452 double fpreg[13];
453
454 // FIXME: why are we restoring the volatile ctr register here
455 sal_Int32 ctrsave = ((sal_Int32*)gpregptr)[-1];
456
457 memcpy( gpreg, gpregptr, 32);
458 memcpy( fpreg, fpregptr, 104);
459
460 volatile long nRegReturn[2];
461
462 // sal_Bool bComplex = nFunctionIndex & 0x80000000 ? sal_True : sal_False;
463
464 typelib_TypeClass aType =
465 cpp_mediate( nFunctionIndex, nVtableOffset, (void**)gpreg, (void**)fpreg, ovrflw, (sal_Int64*)nRegReturn );
466
467 // FIXME: why are we restoring the volatile ctr register here
468 // FIXME: and why are we putting back the values for r4, r5, and r6 as well
469 // FIXME: this makes no sense to me, all of these registers are volatile!
470 __asm__( "lwz r4, %0\n\t"
471 "mtctr r4\n\t"
472 "lwz r4, %1\n\t"
473 "lwz r5, %2\n\t"
474 "lwz r6, %3\n\t"
475 : : "m"(ctrsave), "m"(gpreg[1]), "m"(gpreg[2]), "m"(gpreg[3]) );
476
477 switch( aType )
478 {
479
480 // move return value into register space
481 // (will be loaded by machine code snippet)
482
483 case typelib_TypeClass_BOOLEAN:
484 case typelib_TypeClass_BYTE:
485 __asm__( "lbz r3,%0\n\t" : :
486 "m"(nRegReturn[0]) );
487 break;
488
489 case typelib_TypeClass_CHAR:
490 case typelib_TypeClass_SHORT:
491 case typelib_TypeClass_UNSIGNED_SHORT:
492 __asm__( "lhz r3,%0\n\t" : :
493 "m"(nRegReturn[0]) );
494 break;
495
496 case typelib_TypeClass_FLOAT:
497 __asm__( "lfs f1,%0\n\t" : :
498 "m" (*((float*)nRegReturn)) );
499 break;
500
501 case typelib_TypeClass_DOUBLE:
502 __asm__( "lfd f1,%0\n\t" : :
503 "m" (*((double*)nRegReturn)) );
504 break;
505
506 case typelib_TypeClass_HYPER:
507 case typelib_TypeClass_UNSIGNED_HYPER:
508 __asm__( "lwz r4,%0\n\t" : :
509 "m"(nRegReturn[1]) ); // fall through
510
511 default:
512 __asm__( "lwz r3,%0\n\t" : :
513 "m"(nRegReturn[0]) );
514 break;
515 }
516 }
517
518
519 int const codeSnippetSize = 136;
520
codeSnippet(unsigned char * code,sal_Int32 functionIndex,sal_Int32 vtableOffset,bool simpleRetType)521 unsigned char * codeSnippet( unsigned char * code, sal_Int32 functionIndex,
522 sal_Int32 vtableOffset, bool simpleRetType )
523 {
524 if (! simpleRetType )
525 functionIndex |= 0x80000000;
526
527 // OSL_ASSERT( sizeof (long) == 4 );
528
529 // FIXME: why are we leaving an 8k gap in the stack here
530 // FIXME: is this to allow room for signal handling frames?
531 // FIXME: seems like overkill here but this is what was done for Mac OSX for gcc2
532 // FIXME: also why no saving of the non-volatile CR pieces here, to be safe
533 // FIXME: we probably should
534
535 /* generate this code */
536
537 // # so first save gpr 3 to gpr 10 (aligned to 4)
538 // stw r3, -8000(r1)
539 // stw r4, -7996(r1)
540 // stw r5, -7992(r1)
541 // stw r6, -7988(r1)
542 // stw r7, -7984(r1)
543 // stw r8, -7980(r1)
544 // stw r9, -7976(r1)
545 // stw r10,-7972(r1)
546
547 // # next save fpr 1 to fpr 13 (aligned to 8)
548 // stfd f1, -7968(r1)
549 // stfd f2, -7960(r1)
550 // stfd f3, -7952(r1)
551 // stfd f4, -7944(r1)
552 // stfd f5, -7936(r1)
553 // stfd f6, -7928(r1)
554 // stfd f7, -7920(r1)
555 // stfd f8, -7912(r1)
556 // stfd f9, -7904(r1)
557 // stfd f10,-7896(r1)
558 // stfd f11,-7888(r1)
559 // stfd f12,-7880(r1)
560 // stfd f13,-7872(r1)
561
562 // FIXME: ctr is volatile, while are we saving it and not CR?
563 // mfctr r3
564 // stw r3, -8004(r1)
565
566 // # now here is where cpp_vtable_call must go
567 // lis r3,0xdead
568 // ori r3,r3,0xbeef
569 // mtctr r3
570
571 // # now load up the functionIndex number
572 // lis r3, 0xdead
573 // ori r3,r3,0xbeef
574
575 // # now load up the vtableOffset
576 // lis r4, 0xdead
577 // ori r4,r4,0xbeef
578
579 // #now load up the pointer to the saved gpr registers
580 // addi r5,r1,-8000
581
582 // #now load up the pointer to the saved fpr registers
583 // addi r6,r1,-7968
584
585 // #now load up the pointer to the overflow call stack
586 // addi r7,r1,24 # frame pointer plus 24
587
588 // bctr
589
590 unsigned long * p = (unsigned long *) code;
591
592 * p++ = 0x9061e0c0;
593 * p++ = 0x9081e0c4;
594 * p++ = 0x90a1e0c8;
595 * p++ = 0x90c1e0cc;
596 * p++ = 0x90e1e0d0;
597 * p++ = 0x9101e0d4;
598 * p++ = 0x9121e0d8;
599 * p++ = 0x9141e0dc;
600 * p++ = 0xd821e0e0;
601 * p++ = 0xd841e0e8;
602 * p++ = 0xd861e0f0;
603 * p++ = 0xd881e0f8;
604 * p++ = 0xd8a1e100;
605 * p++ = 0xd8c1e108;
606 * p++ = 0xd8e1e110;
607 * p++ = 0xd901e118;
608 * p++ = 0xd921e120;
609 * p++ = 0xd941e128;
610 * p++ = 0xd961e130;
611 * p++ = 0xd981e138;
612 * p++ = 0xd9a1e140;
613 * p++ = 0x7c6902a6;
614 * p++ = 0x9061e0bc;
615 * p++ = 0x3c600000 | (((unsigned long)cpp_vtable_call) >> 16);
616 * p++ = 0x60630000 | (((unsigned long)cpp_vtable_call) & 0x0000FFFF);
617 * p++ = 0x7c6903a6;
618 * p++ = 0x3c600000 | (((unsigned long)functionIndex) >> 16);
619 * p++ = 0x60630000 | (((unsigned long)functionIndex) & 0x0000FFFF);
620 * p++ = 0x3c800000 | (((unsigned long)vtableOffset) >> 16);
621 * p++ = 0x60840000 | (((unsigned long)vtableOffset) & 0x0000FFFF);
622 * p++ = 0x38a1e0c0;
623 * p++ = 0x38c1e0e0;
624 * p++ = 0x38e10018;
625 * p++ = 0x4e800420;
626
627 return (code + codeSnippetSize);
628
629 }
630
631
632 }
633
flushCode(unsigned char const * bptr,unsigned char const * eptr)634 void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * bptr, unsigned char const * eptr)
635 {
636 int const lineSize = 32;
637 for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) {
638 __asm__ volatile ("dcbst 0, %0" : : "r"(p) : "memory");
639 }
640 __asm__ volatile ("sync" : : : "memory");
641 for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) {
642 __asm__ volatile ("icbi 0, %0" : : "r"(p) : "memory");
643 }
644 __asm__ volatile ("isync" : : : "memory");
645 }
646
647 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
648
649 bridges::cpp_uno::shared::VtableFactory::Slot *
mapBlockToVtable(void * block)650 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
651 {
652 return static_cast< Slot * >(block) + 2;
653 }
654
getBlockSize(sal_Int32 slotCount)655 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
656 sal_Int32 slotCount)
657 {
658 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
659 }
660
661 bridges::cpp_uno::shared::VtableFactory::Slot *
initializeBlock(void * block,sal_Int32 slotCount)662 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
663 void * block, sal_Int32 slotCount)
664 {
665 Slot * slots = mapBlockToVtable(block);
666 slots[-2].fn = 0;
667 slots[-1].fn = 0;
668 return slots + slotCount;
669 }
670
addLocalFunctions(Slot ** slots,unsigned char * code,typelib_InterfaceTypeDescription const * type,sal_Int32 functionOffset,sal_Int32 functionCount,sal_Int32 vtableOffset)671 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
672 Slot ** slots, unsigned char * code,
673 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
674 sal_Int32 functionCount, sal_Int32 vtableOffset)
675 {
676 (*slots) -= functionCount;
677 Slot * s = *slots;
678
679 // fprintf(stderr, "in addLocalFunctions functionOffset is %x\n",functionOffset);
680 // fprintf(stderr, "in addLocalFunctions vtableOffset is %x\n",vtableOffset);
681 // fflush(stderr);
682
683 for (sal_Int32 i = 0; i < type->nMembers; ++i) {
684 typelib_TypeDescription * member = 0;
685 TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
686 OSL_ASSERT(member != 0);
687 switch (member->eTypeClass) {
688 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
689 // Getter:
690 (s++)->fn = code;
691 code = codeSnippet(
692 code, functionOffset++, vtableOffset,
693 bridges::cpp_uno::shared::isSimpleType(
694 reinterpret_cast<
695 typelib_InterfaceAttributeTypeDescription * >(
696 member)->pAttributeTypeRef));
697
698 // Setter:
699 if (!reinterpret_cast<
700 typelib_InterfaceAttributeTypeDescription * >(
701 member)->bReadOnly)
702 {
703 (s++)->fn = code;
704 code = codeSnippet(code, functionOffset++, vtableOffset, true);
705 }
706 break;
707
708 case typelib_TypeClass_INTERFACE_METHOD:
709 (s++)->fn = code;
710 code = codeSnippet(
711 code, functionOffset++, vtableOffset,
712 bridges::cpp_uno::shared::isSimpleType(
713 reinterpret_cast<
714 typelib_InterfaceMethodTypeDescription * >(
715 member)->pReturnTypeRef));
716 break;
717
718 default:
719 OSL_ASSERT(false);
720 break;
721 }
722 TYPELIB_DANGER_RELEASE(member);
723 }
724 return code;
725 }
726
727