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