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