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