xref: /AOO41X/main/bridges/source/cpp_uno/gcc3_macosx_powerpc/cpp2uno.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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 
42 using namespace ::com::sun::star::uno;
43 
44 namespace
45 {
46 
47 //==================================================================================================
48 static typelib_TypeClass cpp2uno_call(
49 	bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
50 	const typelib_TypeDescription * pMemberTypeDescr,
51 	typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
52 	sal_Int32 nParams, typelib_MethodParameter * pParams,
53         void ** gpreg, void ** fpreg, void ** ovrflw,
54 	sal_Int64 * pRegisterReturn /* space for register return */ )
55 {
56 
57         // gpreg:  [ret *], this, [gpr params]
58         // fpreg:  [fpr params]
59         // ovrflw: [gpr or fpr params (space for entire parameter list in structure format properly aligned)]
60 
61 	// return
62 	typelib_TypeDescription * pReturnTypeDescr = 0;
63 	if (pReturnTypeRef)
64 		TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
65 
66 	void * pUnoReturn = 0;
67 	void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
68 
69 	sal_Int32 ngpreg = 0;
70 	sal_Int32 nfpreg = 0;
71 
72 
73 	if (pReturnTypeDescr)
74 	{
75 		if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
76 			pUnoReturn = pRegisterReturn; // direct way for simple types
77 		else // complex return via ptr (pCppReturn)
78 		{
79 			pCppReturn = *gpreg;
80 			ngpreg++;
81 			++ovrflw;
82 
83 			pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
84 						  ? alloca( pReturnTypeDescr->nSize )
85 						  : pCppReturn); // direct way
86 		}
87 	}
88 	// pop this
89 	ngpreg++;
90 	++ovrflw;
91 
92         // after handling optional return pointer and "this"
93         // make use of the space that is allocated to store all parameters in the callers stack
94         // by comying the proper registers filled with parameters to that space
95 	char * pCppStack = (char *)ovrflw;
96 
97 
98 	sal_Int32 nPos;
99 
100 	for ( nPos = 0; nPos < nParams; ++nPos )
101 	{
102 		const typelib_MethodParameter & rParam = pParams[nPos];
103 		if (rParam.bOut)
104 		{
105 			if (ngpreg < 8)
106 			{
107 				*(sal_Int32 *)pCppStack = ((sal_Int32 *)gpreg)[ngpreg++];
108 			}
109 			pCppStack += sizeof (sal_Int32);
110 		}
111 		else
112 		{
113 		switch (rParam.pTypeRef->eTypeClass)
114 		{
115 		case typelib_TypeClass_FLOAT:
116 			if (nfpreg < 13)
117 			{
118 				*(float *)pCppStack = ((double *)fpreg)[nfpreg++];
119 			}
120 			pCppStack += sizeof (float);
121 			ngpreg += 1;
122 			break;
123 		case typelib_TypeClass_DOUBLE:
124 			if (nfpreg < 13)
125 			{
126 				*(double *)pCppStack = ((double *)fpreg)[nfpreg++];
127 			}
128 			pCppStack += sizeof (double);
129 			ngpreg += 2;
130 			break;
131 		case typelib_TypeClass_UNSIGNED_HYPER:
132 		case typelib_TypeClass_HYPER:
133 			if (ngpreg < 8)
134 			{
135 				*(sal_Int32 *)pCppStack = ((sal_Int32 *)gpreg)[ngpreg++];
136 			}
137 			pCppStack += sizeof (sal_Int32);
138                         // fall through on purpose
139 		default:
140 			if (ngpreg < 8)
141 			{
142 				*(sal_Int32 *)pCppStack = ((sal_Int32 *)gpreg)[ngpreg++];
143 			}
144 			pCppStack += sizeof (sal_Int32);
145 		}
146 		}
147 	}
148 
149         // now the stack has all of the paramters stored in it ready to be processed
150         // so we are ready to build the uno call stack
151 	pCppStack = (char *)ovrflw;
152 
153 	// stack space
154 	OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
155 
156 	// parameters
157 	void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
158 	void ** pCppArgs = pUnoArgs + nParams;
159 
160 	// indizes of values this have to be converted (interface conversion cpp<=>uno)
161 	sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
162 
163 	// type descriptions for reconversions
164 	typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
165 
166 	sal_Int32 nTempIndizes   = 0;
167 
168 	for ( nPos = 0; nPos < nParams; ++nPos )
169 	{
170 		const typelib_MethodParameter & rParam = pParams[nPos];
171 		typelib_TypeDescription * pParamTypeDescr = 0;
172 		TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
173 
174 		if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
175                 // value
176 		{
177 			switch (pParamTypeDescr->eTypeClass)
178 			{
179 			case typelib_TypeClass_BOOLEAN:
180 			case typelib_TypeClass_BYTE:
181 				pCppArgs[nPos] = pCppStack +3;
182 				pUnoArgs[nPos] = pCppStack +3;
183 				break;
184 			case typelib_TypeClass_CHAR:
185 			case typelib_TypeClass_SHORT:
186 			case typelib_TypeClass_UNSIGNED_SHORT:
187 				pCppArgs[nPos] = pCppStack +2;
188 				pUnoArgs[nPos] = pCppStack +2;
189 				break;
190 			case typelib_TypeClass_HYPER:
191 			case typelib_TypeClass_UNSIGNED_HYPER:
192 			case typelib_TypeClass_DOUBLE:
193 				pCppArgs[nPos] = pCppStack;
194 				pUnoArgs[nPos] = pCppStack;
195 				pCppStack += sizeof(sal_Int32); // extra long (two regs)
196 				break;
197 			default:
198 				pCppArgs[nPos] = pCppStack;
199 				pUnoArgs[nPos] = pCppStack;
200 			}
201 			// no longer needed
202 			TYPELIB_DANGER_RELEASE( pParamTypeDescr );
203 		}
204 		else // ptr to complex value | ref
205 		{
206 			pCppArgs[nPos] = *(void **)pCppStack;
207 
208 			if (! rParam.bIn) // is pure out
209 			{
210 				// uno out is unconstructed mem!
211 				pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
212 				pTempIndizes[nTempIndizes] = nPos;
213 				// will be released at reconversion
214 				ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
215 			}
216 			// is in/inout
217 			else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
218 			{
219 				uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
220 										*(void **)pCppStack, pParamTypeDescr,
221 										pThis->getBridge()->getCpp2Uno() );
222 				pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
223 				// will be released at reconversion
224 				ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
225 			}
226 			else // direct way
227 			{
228 				pUnoArgs[nPos] = *(void **)pCppStack;
229 				// no longer needed
230 				TYPELIB_DANGER_RELEASE( pParamTypeDescr );
231 			}
232 		}
233 		pCppStack += sizeof(sal_Int32); // standard parameter length
234 	}
235 
236 
237 	// ExceptionHolder
238 	uno_Any aUnoExc; // Any will be constructed by callee
239 	uno_Any * pUnoExc = &aUnoExc;
240 
241 	// invoke uno dispatch call
242 	(*pThis->getUnoI()->pDispatcher)(
243          pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
244 
245 	// in case an exception occured...
246 	if (pUnoExc)
247 	{
248 		// destruct temporary in/inout params
249 		for ( ; nTempIndizes--; )
250 		{
251 			sal_Int32 nIndex = pTempIndizes[nTempIndizes];
252 
253 			if (pParams[nIndex].bIn) // is in/inout => was constructed
254 				uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
255 			TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
256 		}
257 		if (pReturnTypeDescr)
258 			TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
259 
260 		CPPU_CURRENT_NAMESPACE::raiseException(
261                     &aUnoExc, pThis->getBridge()->getUno2Cpp() );
262                 // has to destruct the any
263 		// is here for dummy
264 		return typelib_TypeClass_VOID;
265 	}
266 	else // else no exception occured...
267 	{
268 		// temporary params
269 		for ( ; nTempIndizes--; )
270 		{
271 			sal_Int32 nIndex = pTempIndizes[nTempIndizes];
272 			typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
273 
274 			if (pParams[nIndex].bOut) // inout/out
275 			{
276 				// convert and assign
277 				uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
278 				uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
279 										pThis->getBridge()->getUno2Cpp() );
280 			}
281 			// destroy temp uno param
282 			uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
283 
284 			TYPELIB_DANGER_RELEASE( pParamTypeDescr );
285 		}
286 		// return
287 		if (pCppReturn) // has complex return
288 		{
289 			if (pUnoReturn != pCppReturn) // needs reconversion
290 			{
291 				uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
292 										pThis->getBridge()->getUno2Cpp() );
293 				// destroy temp uno return
294 				uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
295 			}
296 			// complex return ptr is set to return reg
297 			*(void **)pRegisterReturn = pCppReturn;
298 		}
299 		if (pReturnTypeDescr)
300 		{
301 			typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
302 			TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
303 			return eRet;
304 		}
305 		else
306 			return typelib_TypeClass_VOID;
307 	}
308 }
309 
310 
311 //==================================================================================================
312 static typelib_TypeClass cpp_mediate(
313 	sal_Int32 nFunctionIndex,
314         sal_Int32 nVtableOffset,
315         void ** gpreg, void ** fpreg, void ** ovrflw,
316 	sal_Int64 * pRegisterReturn /* space for register return */ )
317 {
318 	OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
319 
320 	// gpreg:  [ret *], this, [other gpr params]
321 	// fpreg:  [fpr params]
322 	// ovrflw: [gpr or fpr params (in space allocated for all params properly aligned)]
323 
324         void * pThis;
325 	if( nFunctionIndex & 0x80000000 )
326 	{
327 		nFunctionIndex &= 0x7fffffff;
328 		pThis = gpreg[1];
329 	}
330 	else
331         {
332 		pThis = gpreg[0];
333         }
334 
335         pThis = static_cast< char * >(pThis) - nVtableOffset;
336         bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
337 	= bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(pThis);
338 
339 
340 	typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
341 
342 	OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
343 	if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
344 	{
345 		throw RuntimeException(
346             rtl::OUString::createFromAscii("illegal vtable index!"),
347             (XInterface *)pThis );
348 	}
349 
350 	// determine called method
351 	sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
352 	OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
353 
354 	TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
355 
356 	typelib_TypeClass eRet;
357 	switch (aMemberDescr.get()->eTypeClass)
358 	{
359 	case typelib_TypeClass_INTERFACE_ATTRIBUTE:
360 	{
361 		if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
362 		{
363 			// is GET method
364 			eRet = cpp2uno_call(
365 				pCppI, aMemberDescr.get(),
366 				((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
367 				0, 0, // no params
368 				gpreg, fpreg, ovrflw, pRegisterReturn );
369 		}
370 		else
371 		{
372 			// is SET method
373 			typelib_MethodParameter aParam;
374 			aParam.pTypeRef =
375 				((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
376 			aParam.bIn		= sal_True;
377 			aParam.bOut		= sal_False;
378 
379 			eRet = cpp2uno_call(
380 				pCppI, aMemberDescr.get(),
381 				0, // indicates void return
382 				1, &aParam,
383 				gpreg, fpreg, ovrflw, pRegisterReturn );
384 		}
385 		break;
386 	}
387 	case typelib_TypeClass_INTERFACE_METHOD:
388 	{
389 		// is METHOD
390 		switch (nFunctionIndex)
391 		{
392 		case 1: // acquire()
393 			pCppI->acquireProxy(); // non virtual call!
394 			eRet = typelib_TypeClass_VOID;
395 			break;
396 		case 2: // release()
397 			pCppI->releaseProxy(); // non virtual call!
398 			eRet = typelib_TypeClass_VOID;
399 			break;
400 		case 0: // queryInterface() opt
401 		{
402 			typelib_TypeDescription * pTD = 0;
403 			TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() );
404 			if (pTD)
405 			{
406                 XInterface * pInterface = 0;
407                 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
408                     pCppI->getBridge()->getCppEnv(),
409                     (void **)&pInterface, pCppI->getOid().pData, (typelib_InterfaceTypeDescription *)pTD );
410 
411                 if (pInterface)
412                 {
413                     ::uno_any_construct(
414                         reinterpret_cast< uno_Any * >( gpreg[0] ),
415                         &pInterface, pTD, cpp_acquire );
416                     pInterface->release();
417                     TYPELIB_DANGER_RELEASE( pTD );
418                     *(void **)pRegisterReturn = gpreg[0];
419                     eRet = typelib_TypeClass_ANY;
420                     break;
421                 }
422                 TYPELIB_DANGER_RELEASE( pTD );
423             }
424 		} // else perform queryInterface()
425 		default:
426 			eRet = cpp2uno_call(
427 				pCppI, aMemberDescr.get(),
428 				((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
429 				((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
430 				((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
431 				gpreg, fpreg, ovrflw, pRegisterReturn );
432 		}
433 		break;
434 	}
435 	default:
436 	{
437 		throw RuntimeException(
438             rtl::OUString::createFromAscii("no member description found!"),
439             (XInterface *)pThis );
440 		// is here for dummy
441 		eRet = typelib_TypeClass_VOID;
442 	}
443 	}
444 
445 	return eRet;
446 }
447 
448 //==================================================================================================
449 /**
450  * is called on incoming vtable calls
451  * (called by asm snippets)
452  */
453 static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** fpregptr, void** ovrflw)
454 {
455         sal_Int32     gpreg[8];
456         double        fpreg[13];
457 
458         // FIXME: why are we restoring the volatile ctr register here
459 	sal_Int32   ctrsave = ((sal_Int32*)gpregptr)[-1];
460 
461         memcpy( gpreg, gpregptr, 32);
462         memcpy( fpreg, fpregptr, 104);
463 
464 	volatile long nRegReturn[2];
465 
466         // sal_Bool bComplex = nFunctionIndex & 0x80000000 ? sal_True : sal_False;
467 
468 	typelib_TypeClass aType =
469              cpp_mediate( nFunctionIndex, nVtableOffset, (void**)gpreg, (void**)fpreg, ovrflw, (sal_Int64*)nRegReturn );
470 
471         // FIXME: why are we restoring the volatile ctr register here
472         // FIXME: and why are we putting back the values for r4, r5, and r6 as well
473         // FIXME: this makes no sense to me, all of these registers are volatile!
474 	__asm__( "lwz r4, %0\n\t"
475 		"mtctr r4\n\t"
476 		"lwz r4, %1\n\t"
477 		"lwz r5, %2\n\t"
478 		"lwz r6, %3\n\t"
479 		 : : "m"(ctrsave), "m"(gpreg[1]), "m"(gpreg[2]), "m"(gpreg[3]) );
480 
481 	switch( aType )
482 	{
483 
484                 // move return value into register space
485                 // (will be loaded by machine code snippet)
486 
487                 case typelib_TypeClass_BOOLEAN:
488                 case typelib_TypeClass_BYTE:
489                   __asm__( "lbz r3,%0\n\t" : :
490 			   "m"(nRegReturn[0]) );
491                   break;
492 
493                 case typelib_TypeClass_CHAR:
494                 case typelib_TypeClass_SHORT:
495                 case typelib_TypeClass_UNSIGNED_SHORT:
496                   __asm__( "lhz r3,%0\n\t" : :
497 			   "m"(nRegReturn[0]) );
498                   break;
499 
500 		case typelib_TypeClass_FLOAT:
501                   __asm__( "lfs f1,%0\n\t" : :
502                            "m" (*((float*)nRegReturn)) );
503 		  break;
504 
505 		case typelib_TypeClass_DOUBLE:
506 		  __asm__( "lfd f1,%0\n\t" : :
507                            "m" (*((double*)nRegReturn)) );
508 		  break;
509 
510 		case typelib_TypeClass_HYPER:
511 		case typelib_TypeClass_UNSIGNED_HYPER:
512 		  __asm__( "lwz r4,%0\n\t" : :
513                            "m"(nRegReturn[1]) );  // fall through
514 
515 		default:
516 		  __asm__( "lwz r3,%0\n\t" : :
517                            "m"(nRegReturn[0]) );
518 		  break;
519 	}
520 }
521 
522 
523 int const codeSnippetSize = 136;
524 
525 unsigned char * codeSnippet( unsigned char * code, sal_Int32 functionIndex,
526                   sal_Int32 vtableOffset, bool simpleRetType )
527 {
528     if (! simpleRetType )
529         functionIndex |= 0x80000000;
530 
531     // OSL_ASSERT( sizeof (long) == 4 );
532 
533     // FIXME: why are we leaving an 8k gap in the stack here
534     // FIXME: is this to allow room for signal handling frames?
535     // FIXME: seems like overkill here but this is what was done for Mac OSX for gcc2
536     // FIXME: also why no saving of the non-volatile CR pieces here, to be safe
537     // FIXME: we probably should
538 
539     /* generate this code */
540 
541     // # so first save gpr 3 to gpr 10 (aligned to 4)
542     //  stw   r3, -8000(r1)
543     //  stw   r4, -7996(r1)
544     //  stw   r5, -7992(r1)
545     //  stw   r6, -7988(r1)
546     //  stw   r7, -7984(r1)
547     //  stw   r8, -7980(r1)
548     //  stw   r9, -7976(r1)
549     //  stw   r10,-7972(r1)
550 
551     // # next save fpr 1 to fpr 13 (aligned to 8)
552     //  stfd  f1, -7968(r1)
553     //  stfd  f2, -7960(r1)
554     //  stfd  f3, -7952(r1)
555     //  stfd  f4, -7944(r1)
556     //  stfd  f5, -7936(r1)
557     //  stfd  f6, -7928(r1)
558     //  stfd  f7, -7920(r1)
559     //  stfd  f8, -7912(r1)
560     //  stfd  f9, -7904(r1)
561     //  stfd  f10,-7896(r1)
562     //  stfd  f11,-7888(r1)
563     //  stfd  f12,-7880(r1)
564     //  stfd  f13,-7872(r1)
565 
566     // FIXME: ctr is volatile, while are we saving it and not CR?
567     // mfctr r3
568     // stw r3, -8004(r1)
569 
570     // # now here is where cpp_vtable_call must go
571     // lis r3,0xdead
572     // ori r3,r3,0xbeef
573     // mtctr r3
574 
575     // # now load up the functionIndex number
576     // lis r3, 0xdead
577     // ori r3,r3,0xbeef
578 
579     // # now load up the vtableOffset
580     // lis r4, 0xdead
581     // ori r4,r4,0xbeef
582 
583     // #now load up the pointer to the saved gpr registers
584     // addi r5,r1,-8000
585 
586     // #now load up the pointer to the saved fpr registers
587     // addi r6,r1,-7968
588 
589     // #now load up the pointer to the overflow call stack
590     // addi r7,r1,24 # frame pointer plus 24
591 
592     // bctr
593 
594     unsigned long * p = (unsigned long *) code;
595 
596     * p++ = 0x9061e0c0;
597     * p++ = 0x9081e0c4;
598     * p++ = 0x90a1e0c8;
599     * p++ = 0x90c1e0cc;
600     * p++ = 0x90e1e0d0;
601     * p++ = 0x9101e0d4;
602     * p++ = 0x9121e0d8;
603     * p++ = 0x9141e0dc;
604     * p++ = 0xd821e0e0;
605     * p++ = 0xd841e0e8;
606     * p++ = 0xd861e0f0;
607     * p++ = 0xd881e0f8;
608     * p++ = 0xd8a1e100;
609     * p++ = 0xd8c1e108;
610     * p++ = 0xd8e1e110;
611     * p++ = 0xd901e118;
612     * p++ = 0xd921e120;
613     * p++ = 0xd941e128;
614     * p++ = 0xd961e130;
615     * p++ = 0xd981e138;
616     * p++ = 0xd9a1e140;
617     * p++ = 0x7c6902a6;
618     * p++ = 0x9061e0bc;
619     * p++ = 0x3c600000 | (((unsigned long)cpp_vtable_call) >> 16);
620     * p++ = 0x60630000 | (((unsigned long)cpp_vtable_call) & 0x0000FFFF);
621     * p++ = 0x7c6903a6;
622     * p++ = 0x3c600000 | (((unsigned long)functionIndex) >> 16);
623     * p++ = 0x60630000 | (((unsigned long)functionIndex) & 0x0000FFFF);
624     * p++ = 0x3c800000 | (((unsigned long)vtableOffset) >> 16);
625     * p++ = 0x60840000 | (((unsigned long)vtableOffset) & 0x0000FFFF);
626     * p++ = 0x38a1e0c0;
627     * p++ = 0x38c1e0e0;
628     * p++ = 0x38e10018;
629     * p++ = 0x4e800420;
630 
631     return (code + codeSnippetSize);
632 
633 }
634 
635 
636 }
637 
638 void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * bptr, unsigned char const * eptr)
639 {
640     int const lineSize = 32;
641     for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) {
642         __asm__ volatile ("dcbst 0, %0" : : "r"(p) : "memory");
643     }
644     __asm__ volatile ("sync" : : : "memory");
645     for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) {
646         __asm__ volatile ("icbi 0, %0" : : "r"(p) : "memory");
647     }
648     __asm__ volatile ("isync" : : : "memory");
649 }
650 
651 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
652 
653 bridges::cpp_uno::shared::VtableFactory::Slot *
654 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
655 {
656     return static_cast< Slot * >(block) + 2;
657 }
658 
659 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
660     sal_Int32 slotCount)
661 {
662     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
663 }
664 
665 bridges::cpp_uno::shared::VtableFactory::Slot *
666 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
667     void * block, sal_Int32 slotCount)
668 {
669     Slot * slots = mapBlockToVtable(block);
670     slots[-2].fn = 0;
671     slots[-1].fn = 0;
672     return slots + slotCount;
673 }
674 
675 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
676     Slot ** slots, unsigned char * code,
677     typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
678     sal_Int32 functionCount, sal_Int32 vtableOffset)
679 {
680     (*slots) -= functionCount;
681     Slot * s = *slots;
682 
683   // fprintf(stderr, "in addLocalFunctions functionOffset is %x\n",functionOffset);
684   // fprintf(stderr, "in addLocalFunctions vtableOffset is %x\n",vtableOffset);
685   // fflush(stderr);
686 
687     for (sal_Int32 i = 0; i < type->nMembers; ++i) {
688         typelib_TypeDescription * member = 0;
689         TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
690         OSL_ASSERT(member != 0);
691         switch (member->eTypeClass) {
692         case typelib_TypeClass_INTERFACE_ATTRIBUTE:
693             // Getter:
694             (s++)->fn = code;
695             code = codeSnippet(
696                 code, functionOffset++, vtableOffset,
697                 bridges::cpp_uno::shared::isSimpleType(
698                     reinterpret_cast<
699                     typelib_InterfaceAttributeTypeDescription * >(
700                         member)->pAttributeTypeRef));
701 
702             // Setter:
703             if (!reinterpret_cast<
704                 typelib_InterfaceAttributeTypeDescription * >(
705                     member)->bReadOnly)
706             {
707                 (s++)->fn = code;
708                 code = codeSnippet(code, functionOffset++, vtableOffset, true);
709             }
710             break;
711 
712         case typelib_TypeClass_INTERFACE_METHOD:
713             (s++)->fn = code;
714             code = codeSnippet(
715                 code, functionOffset++, vtableOffset,
716                 bridges::cpp_uno::shared::isSimpleType(
717                     reinterpret_cast<
718                     typelib_InterfaceMethodTypeDescription * >(
719                         member)->pReturnTypeRef));
720             break;
721 
722         default:
723             OSL_ASSERT(false);
724             break;
725         }
726         TYPELIB_DANGER_RELEASE(member);
727     }
728     return code;
729 }
730 
731