1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 
21 #include <com/sun/star/uno/genfunc.hxx>
22 #include <sal/log.hxx>
23 #include <uno/data.h>
24 #include <typelib/typedescription.hxx>
25 
26 #include "bridge.hxx"
27 #include "cppinterfaceproxy.hxx"
28 #include "types.hxx"
29 #include "vtablefactory.hxx"
30 
31 #include "share.hxx"
32 #include <stdio.h>
33 
34 //Calling Standards:
35 //  "Calling Standard for Alpha Systems"
36 //     (Tru64 UNIX Version 5.1 or higher, August 2000)
37 //http://www.tru64unix.compaq.com/docs/base_doc/DOCUMENTATION/V51_HTML/ARH9MBTE/TITLE.HTM
38 
39 using namespace ::com::sun::star::uno;
40 
41 namespace
42 {
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)43 static typelib_TypeClass cpp2uno_call(
44     bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
45     const typelib_TypeDescription * pMemberTypeDescr,
46     typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
47     sal_Int32 nParams, typelib_MethodParameter * pParams,
48         void ** gpreg, void ** fpreg, void ** ovrflw,
49     sal_Int64 * pRegisterReturn /* space for register return */ )
50 {
51 #if OSL_DEBUG_LEVEL > 2
52     fprintf(stderr, "as far as cpp2uno_call\n");
53 #endif
54     int nregs = 0; //number of words passed in registers
55 
56     // gpreg:  [ret *], this, [gpr params]
57     // fpreg:  [fpr params]
58     // ovrflw: [gpr or fpr params (properly aligned)]
59 
60     // return
61     typelib_TypeDescription * pReturnTypeDescr = 0;
62     if (pReturnTypeRef)
63         TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
64 
65     void * pUnoReturn = 0;
66     void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
67 
68     if (pReturnTypeDescr)
69     {
70         if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
71         {
72             pUnoReturn = pRegisterReturn; // direct way for simple types
73         }
74         else // complex return via ptr (pCppReturn)
75         {
76             pCppReturn = *(void **)gpreg;
77             gpreg++;
78             fpreg++;
79             nregs++;
80 
81             pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
82                           ? alloca( pReturnTypeDescr->nSize )
83                           : pCppReturn); // direct way
84         }
85     }
86     // pop this
87     gpreg++;
88     fpreg++;
89     nregs++;
90 
91     // stack space
92     static_assert(sizeof(void *) == sizeof(sal_Int64), "### unexpected size!");
93     // parameters
94     void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
95     void ** pCppArgs = pUnoArgs + nParams;
96     // indices of values this have to be converted (interface conversion cpp<=>uno)
97     sal_Int32 * pTempIndices = (sal_Int32 *)(pUnoArgs + (2 * nParams));
98     // type descriptions for reconversions
99     typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
100 
101     sal_Int32 nTempIndices   = 0;
102     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
103     {
104         const typelib_MethodParameter & rParam = pParams[nPos];
105         typelib_TypeDescription * pParamTypeDescr = 0;
106         TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
107 
108 #if OSL_DEBUG_LEVEL > 2
109         fprintf(stderr, "arg %d of %d\n", nPos, nParams);
110 #endif
111 
112         if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) // value
113         {
114 #if OSL_DEBUG_LEVEL > 2
115             fprintf(stderr, "simple type is %d\n", pParamTypeDescr->eTypeClass);
116 #endif
117 
118             switch (pParamTypeDescr->eTypeClass)
119             {
120                 case typelib_TypeClass_FLOAT:
121                 case typelib_TypeClass_DOUBLE:
122                     if (nregs < axp::MAX_WORDS_IN_REGS)
123                     {
124                         if (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT)
125                         {
126                             float tmp = (float) (*((double *)fpreg));
127                             (*((float *) fpreg)) = tmp;
128                         }
129 
130                         pCppArgs[nPos] = pUnoArgs[nPos] = fpreg;
131                         gpreg++;
132                         fpreg++;
133                         nregs++;
134                     }
135                     else
136                     {
137                         pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw;
138                         ovrflw++;
139                     }
140                     break;
141                 case typelib_TypeClass_BYTE:
142                 case typelib_TypeClass_BOOLEAN:
143                     if (nregs < axp::MAX_WORDS_IN_REGS)
144                     {
145                         pCppArgs[nPos] = pUnoArgs[nPos] = gpreg;
146                         gpreg++;
147                         fpreg++;
148                         nregs++;
149                     }
150                     else
151                     {
152                         pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw;
153                         ovrflw++;
154                     }
155                     break;
156                 case typelib_TypeClass_CHAR:
157                 case typelib_TypeClass_SHORT:
158                 case typelib_TypeClass_UNSIGNED_SHORT:
159                     if (nregs < axp::MAX_WORDS_IN_REGS)
160                     {
161                         pCppArgs[nPos] = pUnoArgs[nPos] = gpreg;
162                         gpreg++;
163                         fpreg++;
164                         nregs++;
165                     }
166                     else
167                     {
168                         pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw;
169                         ovrflw++;
170                     }
171                     break;
172                 case typelib_TypeClass_ENUM:
173                 case typelib_TypeClass_LONG:
174                 case typelib_TypeClass_UNSIGNED_LONG:
175                     if (nregs < axp::MAX_WORDS_IN_REGS)
176                     {
177                         pCppArgs[nPos] = pUnoArgs[nPos] = gpreg;
178                         gpreg++;
179                         fpreg++;
180                         nregs++;
181                     }
182                     else
183                     {
184                         pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw;
185                         ovrflw++;
186                     }
187                     break;
188                 default:
189                     if (nregs < axp::MAX_WORDS_IN_REGS)
190                     {
191                         pCppArgs[nPos] = pUnoArgs[nPos] = gpreg;
192                         gpreg++;
193                         fpreg++;
194                         nregs++;
195                     }
196                     else
197                     {
198                         pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw;
199                         ovrflw++;
200                     }
201                     break;
202             }
203 
204             // no longer needed
205             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
206         }
207         else // ptr to complex value | ref
208         {
209 #if OSL_DEBUG_LEVEL > 2
210             fprintf(stderr, "complex, nregs is %d\n", nregs);
211 #endif
212 
213             void *pCppStack; //temporary stack pointer
214 
215             if (nregs < axp::MAX_WORDS_IN_REGS)
216             {
217                 pCppArgs[nPos] = pCppStack = *gpreg;
218                 gpreg++;
219                 fpreg++;
220                 nregs++;
221             }
222             else
223             {
224                 pCppArgs[nPos] = pCppStack = *ovrflw;
225                 ovrflw++;
226             }
227 
228             if (! rParam.bIn) // is pure out
229             {
230                 // uno out is unconstructed mem!
231                 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
232                 pTempIndices[nTempIndices] = nPos;
233                 // will be released at reconversion
234                 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
235             }
236             // is in/inout
237             else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
238             {
239                 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
240                                         pCppStack, pParamTypeDescr,
241                                         pThis->getBridge()->getCpp2Uno() );
242                 pTempIndices[nTempIndices] = nPos; // has to be reconverted
243                 // will be released at reconversion
244                 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
245             }
246             else // direct way
247             {
248                 pUnoArgs[nPos] = pCppStack;
249                 // no longer needed
250                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
251             }
252         }
253     }
254 
255 #if OSL_DEBUG_LEVEL > 2
256     fprintf(stderr, "end of params\n");
257 #endif
258 
259     // ExceptionHolder
260     uno_Any aUnoExc; // Any will be constructed by callee
261     uno_Any * pUnoExc = &aUnoExc;
262 
263     // invoke uno dispatch call
264     (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
265 
266     // in case an exception occurred...
267     if (pUnoExc)
268     {
269         // destruct temporary in/inout params
270         for ( ; nTempIndices--; )
271         {
272             sal_Int32 nIndex = pTempIndices[nTempIndices];
273 
274             if (pParams[nIndex].bIn) // is in/inout => was constructed
275                 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndices], 0 );
276             TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
277         }
278         if (pReturnTypeDescr)
279             TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
280 
281         CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
282         // is here for dummy
283         return typelib_TypeClass_VOID;
284     }
285     else // else no exception occurred...
286     {
287         // temporary params
288         for ( ; nTempIndices--; )
289         {
290             sal_Int32 nIndex = pTempIndices[nTempIndices];
291             typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
292 
293             if (pParams[nIndex].bOut) // inout/out
294             {
295                 // convert and assign
296                 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
297                 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
298                                         pThis->getBridge()->getUno2Cpp() );
299             }
300             // destroy temp uno param
301             uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
302 
303             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
304         }
305         // return
306         if (pCppReturn) // has complex return
307         {
308             if (pUnoReturn != pCppReturn) // needs reconversion
309             {
310                 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
311                                         pThis->getBridge()->getUno2Cpp() );
312                 // destroy temp uno return
313                 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
314             }
315             // complex return ptr is set to return reg
316             *(void **)pRegisterReturn = pCppReturn;
317         }
318         if (pReturnTypeDescr)
319         {
320             typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
321             TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
322             return eRet;
323         }
324         else
325             return typelib_TypeClass_VOID;
326     }
327 }
328 
329 
cpp_mediate(sal_uInt64 nOffsetAndIndex,void ** gpreg,void ** fpreg,void ** ovrflw,sal_Int64 * pRegisterReturn)330 static typelib_TypeClass cpp_mediate(
331     sal_uInt64 nOffsetAndIndex,
332     void ** gpreg, void ** fpreg, void ** ovrflw,
333     sal_Int64 * pRegisterReturn /* space for register return */ )
334 {
335     static_assert(sizeof(sal_Int64)==sizeof(void *), "### unexpected!");
336 
337     sal_Int32 nVtableOffset = (nOffsetAndIndex >> 32);
338     sal_Int32 nFunctionIndex = (nOffsetAndIndex & 0xFFFFFFFF);
339 
340 #if OSL_DEBUG_LEVEL > 2
341     fprintf(stderr, "nVTableOffset, nFunctionIndex are %x %x\n", nVtableOffset, nFunctionIndex);
342 #endif
343 
344 #if OSL_DEBUG_LEVEL > 2
345         // Let's figure out what is really going on here
346         {
347             fprintf( stderr, "= cpp_mediate () =\nGPR's (%d): ", 6 );
348             for ( unsigned int i = 0; i < 6; ++i )
349                 fprintf( stderr, "0x%lx, ", gpreg[i] );
350             fprintf( stderr, "\n");
351             fprintf( stderr, "\nFPR's (%d): ", 6 );
352             for ( unsigned int i = 0; i < 6; ++i )
353                 fprintf( stderr, "0x%lx (%f), ", fpreg[i], fpreg[i] );
354             fprintf( stderr, "\n");
355         }
356 #endif
357 
358 
359     // gpreg:  [ret *], this, [other gpr params]
360     // fpreg:  [fpr params]
361     // ovrflw: [gpr or fpr params (properly aligned)]
362 
363     // _this_ ptr is patched cppu_XInterfaceProxy object
364     void * pThis;
365     if( nFunctionIndex & 0x80000000 )
366     {
367         nFunctionIndex &= 0x7fffffff;
368         pThis = gpreg[1];
369     }
370     else
371     {
372         pThis = gpreg[0];
373     }
374 
375     pThis = static_cast< char * >(pThis) - nVtableOffset;
376 
377     bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
378         = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
379             pThis);
380 
381     typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
382 
383 
384     if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
385     {
386         SAL_WARN(
387             "bridges",
388             "illegal " << OUString::unacquired(&pTypeDescr->aBase.pTypeName)
389                 << " vtable index " << nFunctionIndex << "/"
390                 << pTypeDescr->nMapFunctionIndexToMemberIndex);
391         throw RuntimeException(
392             ("illegal " + OUString::unacquired(&pTypeDescr->aBase.pTypeName)
393              + " vtable index " + OUString::number(nFunctionIndex) + "/"
394              + OUString::number(pTypeDescr->nMapFunctionIndexToMemberIndex)),
395             (XInterface *)pCppI);
396     }
397 
398     // determine called method
399     assert(nVtableCall < pTypeDescr->nMapFunctionIndexToMemberIndex);
400     sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
401     assert(nMemberPos < pTypeDescr->nAllMembers);
402 
403     TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
404 
405     typelib_TypeClass eRet;
406     switch (aMemberDescr.get()->eTypeClass)
407     {
408     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
409     {
410         if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
411         {
412             // is GET method
413             eRet = cpp2uno_call(
414                 pCppI, aMemberDescr.get(),
415                 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
416                 0, 0, // no params
417                 gpreg, fpreg, ovrflw, pRegisterReturn );
418         }
419         else
420         {
421             // is SET method
422             typelib_MethodParameter aParam;
423             aParam.pTypeRef =
424                 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
425             aParam.bIn      = sal_True;
426             aParam.bOut     = sal_False;
427 
428             eRet = cpp2uno_call(
429                 pCppI, aMemberDescr.get(),
430                 0, // indicates void return
431                 1, &aParam,
432                 gpreg, fpreg, ovrflw, pRegisterReturn );
433         }
434         break;
435     }
436     case typelib_TypeClass_INTERFACE_METHOD:
437     {
438         // is METHOD
439         switch (nFunctionIndex)
440         {
441         case 1: // acquire()
442             pCppI->acquireProxy(); // non virtual call!
443             eRet = typelib_TypeClass_VOID;
444             break;
445         case 2: // release()
446             pCppI->releaseProxy(); // non virtual call!
447             eRet = typelib_TypeClass_VOID;
448             break;
449         case 0: // queryInterface() opt
450         {
451             typelib_TypeDescription * pTD = 0;
452             TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() );
453             if (pTD)
454             {
455                 XInterface * pInterface = 0;
456                 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
457                     pCppI->getBridge()->getCppEnv(),
458                     (void **)&pInterface, pCppI->getOid().pData,
459                     (typelib_InterfaceTypeDescription *)pTD );
460 
461                 if (pInterface)
462                 {
463                     ::uno_any_construct(
464                         reinterpret_cast< uno_Any * >( gpreg[0] ),
465                         &pInterface, pTD, cpp_acquire );
466                     pInterface->release();
467                     TYPELIB_DANGER_RELEASE( pTD );
468                     *(void **)pRegisterReturn = gpreg[0];
469                     eRet = typelib_TypeClass_ANY;
470                     break;
471                 }
472                 TYPELIB_DANGER_RELEASE( pTD );
473             }
474         } // else perform queryInterface()
475         default:
476             eRet = cpp2uno_call(
477                 pCppI, aMemberDescr.get(),
478                 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
479                 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
480                 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
481                 gpreg, fpreg, ovrflw, pRegisterReturn );
482         }
483         break;
484     }
485     default:
486     {
487         throw RuntimeException( "no member description found!", (XInterface *)pCppI );
488     }
489     }
490 
491     return eRet;
492 }
493 
cpp_vtable_call(long r16,long r17,long r18,long r19,long r20,long r21,long firstonstack)494 long cpp_vtable_call(long r16, long r17, long r18, long r19, long r20, long r21, long firstonstack)
495 {
496     register long r1 asm("$1");
497     sal_uInt64 nOffsetAndIndex = r1;
498 
499     long sp = (long)&firstonstack;
500 
501     sal_uInt64 gpreg[axp::MAX_GPR_REGS];
502     gpreg[0] = r16;
503     gpreg[1] = r17;
504     gpreg[2] = r18;
505     gpreg[3] = r19;
506     gpreg[4] = r20;
507     gpreg[5] = r21;
508 
509     double fpreg[axp::MAX_SSE_REGS];
510     register double f16  asm("$f16");  fpreg[0] = f16;
511     register double f17  asm("$f17");  fpreg[1] = f17;
512     register double f18  asm("$f18");  fpreg[2] = f18;
513     register double f19  asm("$f19");  fpreg[3] = f19;
514     register double f20  asm("$f20");  fpreg[4] = f20;
515     register double f21  asm("$f21");  fpreg[5] = f21;
516 
517     volatile long nRegReturn[1];
518 #if OSL_DEBUG_LEVEL > 2
519     fprintf(stderr, "before mediate with %lx\n",nOffsetAndIndex);
520     fprintf(stderr, "non-doubles are %x %x %x %x %x %x\n", gpreg[0], gpreg[1], gpreg[2], gpreg[3], gpreg[4], gpreg[5]);
521     fprintf(stderr, "doubles are %f %f %f %f %f %f\n", fpreg[0], fpreg[1], fpreg[2], fpreg[3], fpreg[4], fpreg[5]);
522 #endif
523     typelib_TypeClass aType =
524         cpp_mediate( nOffsetAndIndex, (void**)gpreg, (void**)fpreg, (void**)sp,
525             (sal_Int64*)nRegReturn );
526 #if OSL_DEBUG_LEVEL > 2
527     fprintf(stderr, "after mediate ret is %lx %ld\n", nRegReturn[0], nRegReturn[0]);
528 #endif
529 
530     switch( aType )
531     {
532         case typelib_TypeClass_BOOLEAN:
533         case typelib_TypeClass_BYTE:
534             nRegReturn[0] = (unsigned long)(*(unsigned char *)nRegReturn);
535             break;
536         case typelib_TypeClass_CHAR:
537         case typelib_TypeClass_UNSIGNED_SHORT:
538         case typelib_TypeClass_SHORT:
539             nRegReturn[0] = (unsigned long)(*(unsigned short *)nRegReturn);
540             break;
541         case typelib_TypeClass_ENUM:
542         case typelib_TypeClass_UNSIGNED_LONG:
543         case typelib_TypeClass_LONG:
544             nRegReturn[0] = (unsigned long)(*(unsigned int *)nRegReturn);
545             break;
546         case typelib_TypeClass_VOID:
547         default:
548             break;
549         case typelib_TypeClass_FLOAT:
550             {
551                 double tmp = (double) (*((float *)nRegReturn));
552                 (*((double *) nRegReturn)) = tmp;
553             }
554             //deliberate fall through
555         case typelib_TypeClass_DOUBLE:
556             __asm__ ( "ldt $f0,%0\n\t"
557                 : : "m" (*((double*)nRegReturn)) : "$f0");
558             break;
559     }
560     return nRegReturn[0];
561 }
562 
563 const int codeSnippetSize = 32;
564 
codeSnippet(unsigned char * code,sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,bool simple_ret_type)565 unsigned char *codeSnippet( unsigned char * code, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, bool simple_ret_type )
566 {
567     if (! simple_ret_type)
568         nFunctionIndex |= 0x80000000;
569 
570     unsigned char * p = code;
571     *(unsigned int*)&p[0]  = 0x47fb0401;        /* mov $27,$1           */
572     *(unsigned int*)&p[4]  = 0xa43b0010;        /* ldq $1,16($27)      */
573     *(unsigned int*)&p[8]  = 0xa77b0018;        /* ldq $27,24($27)      */
574     *(unsigned int*)&p[12] = 0x6bfb0000;        /* jmp $31,($27),0      */
575     *(unsigned int*)&p[16] = nFunctionIndex;
576     *(unsigned int*)&p[20] = nVtableOffset;
577     *(unsigned long*)&p[24] = (unsigned long)cpp_vtable_call;
578     return (code + codeSnippetSize);
579 }
580 }
581 
flushCode(unsigned char const *,unsigned char const *)582 void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const *, unsigned char const *)
583 {
584     //http://www.gnu.org/software/lightning/manual/html_node/Standard-functions.html
585     __asm__ __volatile__("call_pal 0x86");
586 }
587 
588 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
589 
590 bridges::cpp_uno::shared::VtableFactory::Slot *
mapBlockToVtable(void * block)591 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
592 {
593     return static_cast< Slot * >(block) + 2;
594 }
595 
getBlockSize(sal_Int32 slotCount)596 std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize(
597     sal_Int32 slotCount)
598 {
599     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
600 }
601 
602 bridges::cpp_uno::shared::VtableFactory::Slot *
initializeBlock(void * block,sal_Int32 slotCount,sal_Int32,typelib_InterfaceTypeDescription *)603 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
604     void * block, sal_Int32 slotCount, sal_Int32,
605     typelib_InterfaceTypeDescription *)
606 {
607     Slot * slots = mapBlockToVtable(block);
608     slots[-2].fn = 0;
609     slots[-1].fn = 0;
610     return slots + slotCount;
611 }
612 
addLocalFunctions(Slot ** slots,unsigned char * code,sal_PtrDiff writetoexecdiff,typelib_InterfaceTypeDescription const * type,sal_Int32 functionOffset,sal_Int32 functionCount,sal_Int32 vtableOffset)613 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
614     Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff,
615     typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
616     sal_Int32 functionCount, sal_Int32 vtableOffset)
617 {
618     (*slots) -= functionCount;
619     Slot * s = *slots;
620 #if OSL_DEBUG_LEVEL > 2
621     fprintf(stderr, "in addLocalFunctions functionOffset is %x\n",functionOffset);
622     fprintf(stderr, "in addLocalFunctions vtableOffset is %x\n",vtableOffset);
623 #endif
624 
625     for (sal_Int32 i = 0; i < type->nMembers; ++i) {
626         typelib_TypeDescription * member = 0;
627         TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
628         assert(member != 0);
629         switch (member->eTypeClass) {
630         case typelib_TypeClass_INTERFACE_ATTRIBUTE:
631             // Getter:
632             (s++)->fn = code + writetoexecdiff;
633             code = codeSnippet(
634                 code, functionOffset++, vtableOffset,
635                 bridges::cpp_uno::shared::isSimpleType(
636                     reinterpret_cast<
637                     typelib_InterfaceAttributeTypeDescription * >(
638                         member)->pAttributeTypeRef));
639 
640             // Setter:
641             if (!reinterpret_cast<
642                 typelib_InterfaceAttributeTypeDescription * >(
643                     member)->bReadOnly)
644             {
645                 (s++)->fn = code + writetoexecdiff;
646                 code = codeSnippet(code, functionOffset++, vtableOffset, true);
647             }
648             break;
649 
650         case typelib_TypeClass_INTERFACE_METHOD:
651             (s++)->fn = code + writetoexecdiff;
652             code = codeSnippet(
653                 code, functionOffset++, vtableOffset,
654                 bridges::cpp_uno::shared::isSimpleType(
655                     reinterpret_cast<
656                     typelib_InterfaceMethodTypeDescription * >(
657                         member)->pReturnTypeRef));
658             break;
659 
660         default:
661             assert(false);
662             break;
663         }
664         TYPELIB_DANGER_RELEASE(member);
665     }
666     return code;
667 }
668 
669 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
670