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