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