xref: /trunk/main/bridges/source/cpp_uno/gcc3_linux_mips/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 #include <com/sun/star/uno/genfunc.hxx>
28 #include <typelib/typedescription.hxx>
29 #include <uno/data.h>
30 #include <osl/endian.h>
31 #include "bridges/cpp_uno/shared/bridge.hxx"
32 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
33 #include "bridges/cpp_uno/shared/types.hxx"
34 #include "bridges/cpp_uno/shared/vtablefactory.hxx"
35 #include "share.hxx"
36 
37 #include <stdio.h>
38 #include <string.h>
39 
40 using namespace com::sun::star::uno;
41 
42 //#define BRDEBUG
43 
44 #ifdef BRDEBUG
45 #include <rtl/strbuf.hxx>
46 #include <rtl/ustrbuf.hxx>
47 #include <osl/diagnose.h>
48 #include <osl/mutex.hxx>
49 using namespace ::std;
50 using namespace ::osl;
51 using namespace ::rtl;
52 #endif
53 #include <sys/sysmips.h>
54 
55 #ifdef OSL_BIGENDIAN
56 #define IS_BIG_ENDIAN 1
57 #else
58 #define IS_BIG_ENDIAN 0
59 #endif
60 
61 using namespace ::com::sun::star::uno;
62 
63 namespace
64 {
65 
66   //==================================================================================================
67   static typelib_TypeClass cpp2uno_call(
68       bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
69       const typelib_TypeDescription * pMemberTypeDescr,
70       typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
71       sal_Int32 nParams, typelib_MethodParameter * pParams,
72       void ** gpreg, void ** /*fpreg*/, void ** ovrflw,
73       sal_Int64 * pRegisterReturn /* space for register return */ )
74   {
75     /*  Most MIPS ABIs view the arguments as a struct, of which the
76         first N words go in registers and the rest go on the stack.  If I < N, the
77         Ith word might go in Ith integer argument register or the Ith
78         floating-point one.  For these ABIs, we only need to remember the number
79         of words passed so far.  We are interested only in o32 ABI,so it is the
80         case.
81         */
82     int nw = 0; // number of words used by arguments
83 
84 #ifdef BRDEBUG
85     fprintf(stderr,"cpp2uno_call1\n");
86 #endif
87 
88     /* C++ has [ret *] or this as the first arguments, so no arguments will
89      * be passed in floating-point registers?
90      */
91     //int int_seen = 0; // have we seen integer arguments?
92 
93     void ** pCppStack; //temporary stack pointer
94 
95     // gpreg:  [ret *], this, [gpr params]
96     // fpreg:  [fpr params]
97     // ovrflw: [gpr or fpr params (properly aligned)]
98 
99     // return
100     typelib_TypeDescription * pReturnTypeDescr = 0;
101     if (pReturnTypeRef)
102       TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
103 
104     void * pUnoReturn = 0;
105     void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
106 
107     if (pReturnTypeDescr)
108     {
109       if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
110       {
111         pUnoReturn = pRegisterReturn; // direct way for simple types
112 #ifdef BRDEBUG
113     fprintf(stderr,"cpp2uno_call:simplereturn\n");
114 #endif
115       }
116       else // complex return via ptr (pCppReturn)
117       {
118         pCppReturn = *(void **)gpreg;
119         gpreg++;
120         nw++;
121 
122         pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
123             ? alloca( pReturnTypeDescr->nSize )
124             : pCppReturn); // direct way
125 #ifdef BRDEBUG
126     fprintf(stderr,"cpp2uno_call:complexreturn\n");
127 #endif
128       }
129     }
130 
131     // pop this
132     gpreg++;
133     nw++;
134 
135     // stack space
136     OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
137     // parameters
138     void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
139     void ** pCppArgs = pUnoArgs + nParams;
140     // indizes of values this have to be converted (interface conversion cpp<=>uno)
141     sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
142     // type descriptions for reconversions
143     typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
144 
145     sal_Int32 nTempIndizes   = 0;
146 
147 #ifdef BRDEBUG
148     fprintf(stderr,"cpp2uno_call:nParams=%d\n",nParams);
149 #endif
150 
151     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
152     {
153       const typelib_MethodParameter & rParam = pParams[nPos];
154       typelib_TypeDescription * pParamTypeDescr = 0;
155       TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
156 
157       if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
158         // value
159       {
160 
161         switch (pParamTypeDescr->eTypeClass)
162         {
163           case typelib_TypeClass_DOUBLE:
164           case typelib_TypeClass_HYPER:
165           case typelib_TypeClass_UNSIGNED_HYPER:
166 #ifdef BRDEBUG
167     fprintf(stderr,"cpp2uno_call:hyper=%d,%p\n",pParamTypeDescr->eTypeClass,gpreg[0]);
168 #endif
169             if (nw < 3) {
170               if (nw & 1) {
171                 nw++;
172                 gpreg++;
173               }
174 #ifdef BRDEBUG
175     fprintf(stderr,"cpp2uno_call:gpreg=%p,%p\n",gpreg[0],gpreg[1]);
176 #endif
177               pCppArgs[nPos] = gpreg;
178               pUnoArgs[nPos] = gpreg;
179               nw += 2;
180               gpreg += 2;
181             } else {
182               if (((long)ovrflw) & 4) ovrflw++;
183 #ifdef BRDEBUG
184     fprintf(stderr,"cpp2uno_call:overflw=%p,%p\n",ovrflw[0],ovrflw[1]);
185 #endif
186               pCppArgs[nPos] = ovrflw;
187               pUnoArgs[nPos] = ovrflw;
188               ovrflw += 2;
189             }
190             break;
191 
192           case typelib_TypeClass_BYTE:
193           case typelib_TypeClass_BOOLEAN:
194 #ifdef BRDEBUG
195     fprintf(stderr,"cpp2uno_call:byte=%p,%p\n",gpreg[0],ovrflw[0]);
196 #endif
197             if (nw < 4) {
198               pCppArgs[nPos] = ((char *)gpreg + 3*IS_BIG_ENDIAN);
199               pUnoArgs[nPos] = ((char *)gpreg + 3*IS_BIG_ENDIAN);
200               nw++;
201               gpreg++;
202             } else {
203               pCppArgs[nPos] = ((char *)ovrflw + 3*IS_BIG_ENDIAN);
204               pUnoArgs[nPos] = ((char *)ovrflw + 3*IS_BIG_ENDIAN);
205               ovrflw++;
206             }
207             break;
208 
209 
210           case typelib_TypeClass_CHAR:
211           case typelib_TypeClass_SHORT:
212           case typelib_TypeClass_UNSIGNED_SHORT:
213 #ifdef BRDEBUG
214     fprintf(stderr,"cpp2uno_call:char=%p,%p\n",gpreg[0],ovrflw[0]);
215 #endif
216             if (nw < 4) {
217               pCppArgs[nPos] = ((char *)gpreg + 2*IS_BIG_ENDIAN);
218               pUnoArgs[nPos] = ((char *)gpreg + 2*IS_BIG_ENDIAN);
219               nw++;
220               gpreg++;
221             } else {
222               pCppArgs[nPos] = ((char *)ovrflw + 2*IS_BIG_ENDIAN);
223               pUnoArgs[nPos] = ((char *)ovrflw + 2*IS_BIG_ENDIAN);
224               ovrflw++;
225             }
226             break;
227 
228 
229           default:
230 #ifdef BRDEBUG
231     fprintf(stderr,"cpp2uno_call:def=%p,%p\n",gpreg[0],ovrflw[0]);
232 #endif
233             if (nw < 4) {
234               pCppArgs[nPos] = gpreg;
235               pUnoArgs[nPos] = gpreg;
236               nw++;
237               gpreg++;
238             } else {
239               pCppArgs[nPos] = ovrflw;
240               pUnoArgs[nPos] = ovrflw;
241               ovrflw++;
242             }
243             break;
244 
245         }
246         // no longer needed
247         TYPELIB_DANGER_RELEASE( pParamTypeDescr );
248       }
249       else // ptr to complex value | ref
250       {
251 
252 #ifdef BRDEBUG
253     fprintf(stderr,"cpp2uno_call:ptr|ref\n");
254 #endif
255         if (nw < 4) {
256           pCppArgs[nPos] = *(void **)gpreg;
257           pCppStack = gpreg;
258           nw++;
259           gpreg++;
260         } else {
261           pCppArgs[nPos] = *(void **)ovrflw;
262           pCppStack = ovrflw;
263           ovrflw++;
264         }
265 #ifdef BRDEBUG
266     fprintf(stderr,"cpp2uno_call:pCppStack=%p\n",pCppStack);
267 #endif
268 
269         if (! rParam.bIn) // is pure out
270         {
271           // uno out is unconstructed mem!
272           pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
273           pTempIndizes[nTempIndizes] = nPos;
274           // will be released at reconversion
275           ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
276         }
277         // is in/inout
278         else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
279         {
280           uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
281               *(void **)pCppStack, pParamTypeDescr,
282               pThis->getBridge()->getCpp2Uno() );
283           pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
284           // will be released at reconversion
285           ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
286 #ifdef BRDEBUG
287     fprintf(stderr,"cpp2uno_call:related to interface,%p,%d,pUnoargs[%d]=%p\n",*(void**)pCppStack,pParamTypeDescr->nSize,nPos,pUnoArgs[nPos]);
288 #endif
289         }
290         else // direct way
291         {
292           pUnoArgs[nPos] = *(void **)pCppStack;
293 #ifdef BRDEBUG
294     fprintf(stderr,"cpp2uno_call:direct,pUnoArgs[%d]=%p\n",nPos,pUnoArgs[nPos]);
295 #endif
296           // no longer needed
297           TYPELIB_DANGER_RELEASE( pParamTypeDescr );
298         }
299       }
300     }
301 #ifdef BRDEBUG
302     fprintf(stderr,"cpp2uno_call2,%p,unoargs=%p\n",pThis->getUnoI()->pDispatcher,pUnoArgs);
303 #endif
304 
305     // ExceptionHolder
306     uno_Any aUnoExc; // Any will be constructed by callee
307     uno_Any * pUnoExc = &aUnoExc;
308 
309     // invoke uno dispatch call
310     (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
311 #ifdef BRDEBUG
312     fprintf(stderr,"cpp2uno_call2,after dispatch\n");
313 #endif
314 
315     // in case an exception occured...
316     if (pUnoExc)
317     {
318       // destruct temporary in/inout params
319       for ( ; nTempIndizes--; )
320       {
321         sal_Int32 nIndex = pTempIndizes[nTempIndizes];
322 
323         if (pParams[nIndex].bIn) // is in/inout => was constructed
324           uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
325         TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
326       }
327       if (pReturnTypeDescr)
328         TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
329 
330       CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() );
331       // has to destruct the any
332       // is here for dummy
333       return typelib_TypeClass_VOID;
334     }
335     else // else no exception occured...
336     {
337       // temporary params
338       for ( ; nTempIndizes--; )
339       {
340         sal_Int32 nIndex = pTempIndizes[nTempIndizes];
341         typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
342 
343         if (pParams[nIndex].bOut) // inout/out
344         {
345           // convert and assign
346           uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
347           uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
348               pThis->getBridge()->getUno2Cpp() );
349         }
350         // destroy temp uno param
351         uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
352 
353         TYPELIB_DANGER_RELEASE( pParamTypeDescr );
354       }
355       // return
356       if (pCppReturn) // has complex return
357       {
358         if (pUnoReturn != pCppReturn) // needs reconversion
359         {
360           uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
361               pThis->getBridge()->getUno2Cpp() );
362           // destroy temp uno return
363           uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
364         }
365         // complex return ptr is set to return reg
366         *(void **)pRegisterReturn = pCppReturn;
367       }
368       if (pReturnTypeDescr)
369       {
370         typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
371         TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
372         return eRet;
373       }
374       else
375         return typelib_TypeClass_VOID;
376     }
377   }
378 
379 
380   //==================================================================================================
381   static typelib_TypeClass cpp_mediate(
382       sal_Int32 nFunctionIndex,
383       sal_Int32 nVtableOffset,
384       void ** gpreg, void ** fpreg, void ** ovrflw,
385       sal_Int64 * pRegisterReturn /* space for register return */ )
386   {
387     OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
388 
389 #ifdef BRDEBUG
390     fprintf(stderr,"cpp_mediate1 gp=%p,fp=%p,ov=%p\n",gpreg,fpreg,ovrflw);
391     fprintf(stderr,"gp=%x,%x,%x,%x\n",gpreg[0],gpreg[1],gpreg[2],gpreg[3]);
392 #endif
393 
394     // gpreg:  [ret *], this, [other gpr params]
395     // fpreg:  [fpr params]
396     // ovrflw: [gpr or fpr params (properly aligned)]
397 
398     void * pThis;
399     if (nFunctionIndex & 0x80000000 )
400     {
401       nFunctionIndex &= 0x7fffffff;
402       pThis = gpreg[1];
403     }
404     else
405     {
406       pThis = gpreg[0];
407     }
408 #ifdef BRDEBUG
409     fprintf(stderr,"cpp_mediate12,pThis=%p, nFunctionIndex=%d,nVtableOffset=%d\n",pThis,nFunctionIndex,nVtableOffset);
410 #endif
411 
412     pThis = static_cast< char * >(pThis) - nVtableOffset;
413     bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
414       = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
415           pThis);
416 #ifdef BRDEBUG
417     fprintf(stderr,"cpp_mediate13,pCppI=%p\n",pCppI);
418 #endif
419 
420     typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
421 
422 #ifdef BRDEBUG
423     fprintf(stderr,"cpp_mediate2\n");
424 #endif
425     OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
426     if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
427     {
428       throw RuntimeException(
429           rtl::OUString::createFromAscii("illegal vtable index!"),
430           (XInterface *)pThis );
431     }
432 
433     // determine called method
434     sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
435     OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
436 
437     TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
438 
439 #ifdef BRDEBUG
440     fprintf(stderr,"cpp_mediate3\n");
441     OString cstr( OUStringToOString( aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
442     fprintf( stderr, "calling %s, nFunctionIndex=%d\n", cstr.getStr(), nFunctionIndex );
443 #endif
444     typelib_TypeClass eRet;
445     switch (aMemberDescr.get()->eTypeClass)
446     {
447       case typelib_TypeClass_INTERFACE_ATTRIBUTE:
448         {
449 #ifdef BRDEBUG
450     fprintf(stderr,"cpp_mediate4\n");
451 #endif
452           if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
453           {
454             // is GET method
455             eRet = cpp2uno_call(
456                 pCppI, aMemberDescr.get(),
457                 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
458                 0, 0, // no params
459                 gpreg, fpreg, ovrflw, pRegisterReturn );
460           }
461           else
462           {
463             // is SET method
464             typelib_MethodParameter aParam;
465             aParam.pTypeRef =
466               ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
467             aParam.bIn      = sal_True;
468             aParam.bOut     = sal_False;
469 
470             eRet = cpp2uno_call(
471                 pCppI, aMemberDescr.get(),
472                 0, // indicates void return
473                 1, &aParam,
474                 gpreg, fpreg, ovrflw, pRegisterReturn );
475           }
476           break;
477         }
478       case typelib_TypeClass_INTERFACE_METHOD:
479         {
480 #ifdef BRDEBUG
481     fprintf(stderr,"cpp_mediate5\n");
482 #endif
483           // is METHOD
484           switch (nFunctionIndex)
485           {
486             case 1: // acquire()
487               pCppI->acquireProxy(); // non virtual call!
488               eRet = typelib_TypeClass_VOID;
489               break;
490             case 2: // release()
491 #ifdef BRDEBUG
492     fprintf(stderr,"cpp_mediate51\n");
493 #endif
494               pCppI->releaseProxy(); // non virtual call!
495               eRet = typelib_TypeClass_VOID;
496 #ifdef BRDEBUG
497     fprintf(stderr,"cpp_mediate52\n");
498 #endif
499               break;
500             case 0: // queryInterface() opt
501               {
502                 typelib_TypeDescription * pTD = 0;
503                 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() );
504                 if (pTD)
505                 {
506                   XInterface * pInterface = 0;
507                   (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
508                                                                              pCppI->getBridge()->getCppEnv(),
509                                                                              (void **)&pInterface, pCppI->getOid().pData,
510                                                                              (typelib_InterfaceTypeDescription *)pTD );
511 
512                   if (pInterface)
513                   {
514                     ::uno_any_construct(
515                         reinterpret_cast< uno_Any * >( gpreg[0] ),
516                         &pInterface, pTD, cpp_acquire );
517                     pInterface->release();
518                     TYPELIB_DANGER_RELEASE( pTD );
519                     *(void **)pRegisterReturn = gpreg[0];
520                     eRet = typelib_TypeClass_ANY;
521                     break;
522                   }
523                   TYPELIB_DANGER_RELEASE( pTD );
524                 }
525               } // else perform queryInterface()
526             default:
527               eRet = cpp2uno_call(
528                   pCppI, aMemberDescr.get(),
529                   ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
530                   ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
531                   ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
532                   gpreg, fpreg, ovrflw, pRegisterReturn );
533           }
534           break;
535         }
536       default:
537         {
538 #ifdef BRDEBUG
539     fprintf(stderr,"cpp_mediate6\n");
540 #endif
541           throw RuntimeException(
542               rtl::OUString::createFromAscii("no member description found!"),
543               (XInterface *)pThis );
544           // is here for dummy
545           eRet = typelib_TypeClass_VOID;
546         }
547     }
548 
549     return eRet;
550   }
551 
552   //==================================================================================================
553   /**
554    * is called on incoming vtable calls
555    * (called by asm snippets)
556    */
557 //  static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** fpregptr, void** ovrflw)
558 //  static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** ovrflw)
559   static void cpp_vtable_call(void)
560   {
561     int nFunctionIndex;
562     int vTableOffset;
563     void** pCallStack;
564     void** ovrflw;
565 
566     sal_Int32     gpreg[4];
567     double        fpreg[2];
568 
569     //memcpy( fpreg, fpregptr, 16);
570 
571     volatile long nRegReturn[2];
572 
573     __asm__( "sw $4, %0\n\t"
574          "sw $5, %1\n\t"
575          "sw $6, %2\n\t"
576          "sw $7, %3\n\t"
577             ::"m"(nFunctionIndex), "m"(vTableOffset), "m"(pCallStack), "m"(ovrflw) );
578 
579     memcpy( gpreg, pCallStack, 16);
580 
581 #ifdef BRDEBUG
582     fprintf(stderr,"in cpp_vtable_call nFunctionIndex is %d\n",nFunctionIndex);
583     fprintf(stderr,"in cpp_vtable_call nVtableOffset is %d\n",vTableOffset);
584     fprintf(stderr,"gp=%x,%x,%x,%x\n",gpreg[0],gpreg[1],gpreg[2],gpreg[3]);
585 #endif
586 
587     //sal_Bool bComplex = nFunctionIndex & 0x80000000 ? sal_True : sal_False;
588 
589     typelib_TypeClass aType =
590       cpp_mediate( nFunctionIndex, vTableOffset, (void**)gpreg, (void**)fpreg, ovrflw, (sal_Int64*)nRegReturn );
591 
592     switch( aType )
593     {
594 
595       // move return value into register space
596       // (will be loaded by machine code snippet)
597 
598       case typelib_TypeClass_BOOLEAN:
599       case typelib_TypeClass_BYTE:
600         __asm__( "lbu $2,%0\n\t" : :
601             "m"(nRegReturn[0]) );
602         break;
603 
604       case typelib_TypeClass_CHAR:
605       case typelib_TypeClass_UNSIGNED_SHORT:
606         __asm__( "lhu $2,%0\n\t" : :
607             "m"(nRegReturn[0]) );
608         break;
609 
610       case typelib_TypeClass_SHORT:
611         __asm__( "lh $2,%0\n\t" : :
612             "m"(nRegReturn[0]) );
613         break;
614 
615 
616       case typelib_TypeClass_FLOAT:
617         __asm__( "lwc1 $f0,%0\n\t" : :
618             "m" (*((float*)nRegReturn)) );
619         break;
620 
621       case typelib_TypeClass_DOUBLE:
622         { register double dret asm("$f0");
623         dret = (*((double*)nRegReturn)); }
624         break;
625 
626       case typelib_TypeClass_HYPER:
627       case typelib_TypeClass_UNSIGNED_HYPER:
628         __asm__( "lw $3,%0\n\t" : :
629             "m"(nRegReturn[1]) );  // fall through
630 
631       default:
632         __asm__( "lw $2,%0\n\t" : :
633             "m"(nRegReturn[0]) );
634         break;
635     }
636   }
637 
638 
639   int const codeSnippetSize = 56;
640 
641   unsigned char *  codeSnippet( unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
642       bool simpleRetType)
643   {
644 
645 #ifdef BRDEBUG
646      fprintf(stderr,"in codeSnippet functionIndex is %d\n", functionIndex);
647      fprintf(stderr,"in codeSnippet vtableOffset is %d\n", vtableOffset);
648      fflush(stderr);
649 #endif
650 
651     if (! simpleRetType )
652       functionIndex |= 0x80000000;
653 
654     unsigned long * p = (unsigned long *) code;
655 
656     // OSL_ASSERT( sizeof (long) == 4 );
657     OSL_ASSERT((((unsigned long)code) & 0x3) == 0 );  //aligned to 4 otherwise a mistake
658 
659     /* generate this code */
660     /*
661        #save regs into argument space required by mips abi
662             c:   afa40000        sw      a0,0(sp)
663        10:   afa50004        sw      a1,4(sp)
664        14:   afa60008        sw      a2,8(sp)
665        18:   afa7000c        sw      a3,12(sp)
666        #a0=index
667        1c:   3c040000        lui     a0,0x0
668        20:   34840000        ori     a0,a0,0x0
669        #a1=offset
670        24:   3c050000        lui     a1,0x0
671        28:   34a50000        ori     a1,a1,0x0
672        #a2=gpregptr
673        2c:   27a60000        addiu   a2,sp,0
674        #a3=ovrflw
675        30:   27a70010        addiu   a3,sp,16
676        #load cpp_vtable_call addr
677        34:   3c190000        lui     t9,0x0
678        38:   37390000        ori     t9,t9,0
679        #jmp to the function,note: we don't use jalr, that will destroy $ra
680        #but be sure to use t9! gp calculation depends on it
681        3c:   03200008        jr      t9
682        40:   00000000        nop
683 
684        be careful, we use the argument space reserved by the caller to
685        write down regs. This can avoid the need to make use of arbitary far away
686        stack space or to allocate a function frame for this code snippet itself.
687        Since only functions with variable arguments will overwrite the space,
688        cpp_vtable_call should be safe.
689        ??? gcc seems change this behavior! cpp_vtable_call overwrite the space!
690      */
691 
692     * p++ = 0xafa40000;
693     * p++ = 0xafa50004;
694     * p++ = 0xafa60008;
695     * p++ = 0xafa7000c;
696     * p++ = 0x3c040000 | ((functionIndex>>16) & 0x0000ffff);
697     * p++ = 0x34840000 | (functionIndex & 0x0000ffff);
698     * p++ = 0x3c050000 | ((vtableOffset>>16) & 0x0000ffff);
699     * p++ = 0x34a50000 | (vtableOffset & 0x0000ffff);
700     * p++ = 0x27a60000;
701     * p++ = 0x27a70010;
702     * p++ = 0x3c190000 | ((((unsigned long)cpp_vtable_call) >> 16) & 0x0000ffff);
703     * p++ = 0x37390000 | (((unsigned long)cpp_vtable_call) & 0x0000FFFF);
704     * p++ = 0x03200008;
705     * p++ = 0x00000000;
706     return (code + codeSnippetSize);
707 
708   }
709 
710 
711 }
712 
713 
714 #define MIN_LINE_SIZE 32
715 
716 void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * /*bptr*/, unsigned char const * /*eptr*/)
717 {
718   sysmips(FLUSH_CACHE,0,0,0);
719 }
720 
721 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
722 
723 bridges::cpp_uno::shared::VtableFactory::Slot *
724 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
725 {
726     return static_cast< Slot * >(block) + 2;
727 }
728 
729 
730 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
731     sal_Int32 slotCount)
732 {
733     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
734 }
735 
736 bridges::cpp_uno::shared::VtableFactory::Slot *
737 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
738     void * block, sal_Int32 slotCount)
739 {
740     Slot * slots = mapBlockToVtable(block);
741     slots[-2].fn = 0; //null
742     slots[-1].fn = 0; //destructor
743     return slots + slotCount;
744 }
745 
746 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
747     Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff,
748     typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
749     sal_Int32 functionCount, sal_Int32 vtableOffset)
750 {
751    (*slots) -= functionCount;
752     Slot * s = *slots;
753 #ifdef BRDEBUG
754    fprintf(stderr, "in addLocalFunctions functionOffset is %d\n",functionOffset);
755    fprintf(stderr, "in addLocalFunctions vtableOffset is %d\n",vtableOffset);
756    fprintf(stderr, "nMembers=%d\n",type->nMembers);
757    fflush(stderr);
758 #endif
759 
760   for (sal_Int32 i = 0; i < type->nMembers; ++i) {
761     typelib_TypeDescription * member = 0;
762     TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
763     OSL_ASSERT(member != 0);
764     switch (member->eTypeClass) {
765       case typelib_TypeClass_INTERFACE_ATTRIBUTE:
766         // Getter:
767         (s++)->fn = code + writetoexecdiff;
768         code = codeSnippet(
769             code, functionOffset++, vtableOffset,
770             bridges::cpp_uno::shared::isSimpleType(
771               reinterpret_cast<
772               typelib_InterfaceAttributeTypeDescription * >(
773                 member)->pAttributeTypeRef));
774 
775         // Setter:
776         if (!reinterpret_cast<
777             typelib_InterfaceAttributeTypeDescription * >(
778               member)->bReadOnly)
779         {
780           (s++)->fn = code + writetoexecdiff;
781           code = codeSnippet(code, functionOffset++, vtableOffset, true);
782         }
783         break;
784 
785       case typelib_TypeClass_INTERFACE_METHOD:
786         (s++)->fn = code + writetoexecdiff;
787         code = codeSnippet(
788             code, functionOffset++, vtableOffset,
789             bridges::cpp_uno::shared::isSimpleType(
790               reinterpret_cast<
791               typelib_InterfaceMethodTypeDescription * >(
792                 member)->pReturnTypeRef));
793         break;
794 
795       default:
796         OSL_ASSERT(false);
797         break;
798     }
799     TYPELIB_DANGER_RELEASE(member);
800   }
801   return code;
802 }
803 
804