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