xref: /AOO41X/main/bridges/source/cpp_uno/gcc3_macosx_powerpc/cpp2uno.cxx (revision 61dff127b6698e0bae836c8aedd6ec62111483d1)
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