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