xref: /AOO41X/main/bridges/source/cpp_uno/gcc3_linux_mips/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 #include <com/sun/star/uno/genfunc.hxx>
28 #include <typelib/typedescription.hxx>
29 #include <uno/data.h>
30 #include <osl/endian.h>
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 #include "share.hxx"
36 
37 #include <stdio.h>
38 #include <string.h>
39 
40 using namespace com::sun::star::uno;
41 
42 //#define BRDEBUG
43 
44 #ifdef BRDEBUG
45 #include <rtl/strbuf.hxx>
46 #include <rtl/ustrbuf.hxx>
47 #include <osl/diagnose.h>
48 #include <osl/mutex.hxx>
49 using namespace ::std;
50 using namespace ::osl;
51 using namespace ::rtl;
52 #endif
53 #include <sys/sysmips.h>
54 
55 #ifdef OSL_BIGENDIAN
56 #define IS_BIG_ENDIAN 1
57 #else
58 #define IS_BIG_ENDIAN 0
59 #endif
60 
61 using namespace ::com::sun::star::uno;
62 
63 namespace
64 {
65 
66   //==================================================================================================
67   static typelib_TypeClass cpp2uno_call(
68 	  bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
69 	  const typelib_TypeDescription * pMemberTypeDescr,
70 	  typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
71 	  sal_Int32 nParams, typelib_MethodParameter * pParams,
72 	  void ** gpreg, void ** /*fpreg*/, void ** ovrflw,
73 	  sal_Int64 * pRegisterReturn /* space for register return */ )
74   {
75 	/*  Most MIPS ABIs view the arguments as a struct, of which the
76 		first N words go in registers and the rest go on the stack.  If I < N, the
77 		Ith word might go in Ith integer argument register or the Ith
78 		floating-point one.  For these ABIs, we only need to remember the number
79 		of words passed so far.  We are interested only in o32 ABI,so it is the
80 		case.
81 		*/
82 	int nw = 0; // number of words used by arguments
83 
84 #ifdef BRDEBUG
85 	fprintf(stderr,"cpp2uno_call1\n");
86 #endif
87 
88 	/* C++ has [ret *] or this as the first arguments, so no arguments will
89 	 * be passed in floating-point registers?
90 	 */
91 	//int int_seen = 0; // have we seen integer arguments?
92 
93 	void ** pCppStack; //temporary stack pointer
94 
95 	// gpreg:  [ret *], this, [gpr params]
96 	// fpreg:  [fpr params]
97 	// ovrflw: [gpr or fpr params (properly aligned)]
98 
99 	// return
100 	typelib_TypeDescription * pReturnTypeDescr = 0;
101 	if (pReturnTypeRef)
102 	  TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
103 
104 	void * pUnoReturn = 0;
105 	void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
106 
107 	if (pReturnTypeDescr)
108 	{
109 	  if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
110 	  {
111 		pUnoReturn = pRegisterReturn; // direct way for simple types
112 #ifdef BRDEBUG
113 	fprintf(stderr,"cpp2uno_call:simplereturn\n");
114 #endif
115 	  }
116 	  else // complex return via ptr (pCppReturn)
117 	  {
118 		pCppReturn = *(void **)gpreg;
119 		gpreg++;
120 		nw++;
121 
122 		pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
123 			? alloca( pReturnTypeDescr->nSize )
124 			: pCppReturn); // direct way
125 #ifdef BRDEBUG
126 	fprintf(stderr,"cpp2uno_call:complexreturn\n");
127 #endif
128 	  }
129 	}
130 
131 	// pop this
132 	gpreg++;
133 	nw++;
134 
135 	// stack space
136 	OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
137 	// parameters
138 	void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
139 	void ** pCppArgs = pUnoArgs + nParams;
140 	// indizes of values this have to be converted (interface conversion cpp<=>uno)
141 	sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
142 	// type descriptions for reconversions
143 	typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
144 
145 	sal_Int32 nTempIndizes   = 0;
146 
147 #ifdef BRDEBUG
148 	fprintf(stderr,"cpp2uno_call:nParams=%d\n",nParams);
149 #endif
150 
151 	for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
152 	{
153 	  const typelib_MethodParameter & rParam = pParams[nPos];
154 	  typelib_TypeDescription * pParamTypeDescr = 0;
155 	  TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
156 
157 	  if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
158 		// value
159 	  {
160 
161 		switch (pParamTypeDescr->eTypeClass)
162 		{
163 		  case typelib_TypeClass_DOUBLE:
164 		  case typelib_TypeClass_HYPER:
165 		  case typelib_TypeClass_UNSIGNED_HYPER:
166 #ifdef BRDEBUG
167 	fprintf(stderr,"cpp2uno_call:hyper=%d,%p\n",pParamTypeDescr->eTypeClass,gpreg[0]);
168 #endif
169 			if (nw < 3) {
170 			  if (nw & 1) {
171 				nw++;
172 				gpreg++;
173 			  }
174 #ifdef BRDEBUG
175 	fprintf(stderr,"cpp2uno_call:gpreg=%p,%p\n",gpreg[0],gpreg[1]);
176 #endif
177 			  pCppArgs[nPos] = gpreg;
178 			  pUnoArgs[nPos] = gpreg;
179 			  nw += 2;
180 			  gpreg += 2;
181 			} else {
182 			  if (((long)ovrflw) & 4) ovrflw++;
183 #ifdef BRDEBUG
184 	fprintf(stderr,"cpp2uno_call:overflw=%p,%p\n",ovrflw[0],ovrflw[1]);
185 #endif
186 			  pCppArgs[nPos] = ovrflw;
187 			  pUnoArgs[nPos] = ovrflw;
188 			  ovrflw += 2;
189 			}
190 			break;
191 
192 		  case typelib_TypeClass_BYTE:
193 		  case typelib_TypeClass_BOOLEAN:
194 #ifdef BRDEBUG
195 	fprintf(stderr,"cpp2uno_call:byte=%p,%p\n",gpreg[0],ovrflw[0]);
196 #endif
197 			if (nw < 4) {
198 			  pCppArgs[nPos] = ((char *)gpreg + 3*IS_BIG_ENDIAN);
199 			  pUnoArgs[nPos] = ((char *)gpreg + 3*IS_BIG_ENDIAN);
200 			  nw++;
201 			  gpreg++;
202 			} else {
203 			  pCppArgs[nPos] = ((char *)ovrflw + 3*IS_BIG_ENDIAN);
204 			  pUnoArgs[nPos] = ((char *)ovrflw + 3*IS_BIG_ENDIAN);
205 			  ovrflw++;
206 			}
207 			break;
208 
209 
210 		  case typelib_TypeClass_CHAR:
211 		  case typelib_TypeClass_SHORT:
212 		  case typelib_TypeClass_UNSIGNED_SHORT:
213 #ifdef BRDEBUG
214 	fprintf(stderr,"cpp2uno_call:char=%p,%p\n",gpreg[0],ovrflw[0]);
215 #endif
216 			if (nw < 4) {
217 			  pCppArgs[nPos] = ((char *)gpreg + 2*IS_BIG_ENDIAN);
218 			  pUnoArgs[nPos] = ((char *)gpreg + 2*IS_BIG_ENDIAN);
219 			  nw++;
220 			  gpreg++;
221 			} else {
222 			  pCppArgs[nPos] = ((char *)ovrflw + 2*IS_BIG_ENDIAN);
223 			  pUnoArgs[nPos] = ((char *)ovrflw + 2*IS_BIG_ENDIAN);
224 			  ovrflw++;
225 			}
226 			break;
227 
228 
229 		  default:
230 #ifdef BRDEBUG
231 	fprintf(stderr,"cpp2uno_call:def=%p,%p\n",gpreg[0],ovrflw[0]);
232 #endif
233 			if (nw < 4) {
234 			  pCppArgs[nPos] = gpreg;
235 			  pUnoArgs[nPos] = gpreg;
236 			  nw++;
237 			  gpreg++;
238 			} else {
239 			  pCppArgs[nPos] = ovrflw;
240 			  pUnoArgs[nPos] = ovrflw;
241 			  ovrflw++;
242 			}
243 			break;
244 
245 		}
246 		// no longer needed
247 		TYPELIB_DANGER_RELEASE( pParamTypeDescr );
248 	  }
249 	  else // ptr to complex value | ref
250 	  {
251 
252 #ifdef BRDEBUG
253 	fprintf(stderr,"cpp2uno_call:ptr|ref\n");
254 #endif
255 		if (nw < 4) {
256 		  pCppArgs[nPos] = *(void **)gpreg;
257 		  pCppStack = gpreg;
258 		  nw++;
259 		  gpreg++;
260 		} else {
261 		  pCppArgs[nPos] = *(void **)ovrflw;
262 		  pCppStack = ovrflw;
263 		  ovrflw++;
264 		}
265 #ifdef BRDEBUG
266 	fprintf(stderr,"cpp2uno_call:pCppStack=%p\n",pCppStack);
267 #endif
268 
269 		if (! rParam.bIn) // is pure out
270 		{
271 		  // uno out is unconstructed mem!
272 		  pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
273 		  pTempIndizes[nTempIndizes] = nPos;
274 		  // will be released at reconversion
275 		  ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
276 		}
277 		// is in/inout
278 		else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
279 		{
280 		  uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
281 			  *(void **)pCppStack, pParamTypeDescr,
282 			  pThis->getBridge()->getCpp2Uno() );
283 		  pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
284 		  // will be released at reconversion
285 		  ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
286 #ifdef BRDEBUG
287 	fprintf(stderr,"cpp2uno_call:related to interface,%p,%d,pUnoargs[%d]=%p\n",*(void**)pCppStack,pParamTypeDescr->nSize,nPos,pUnoArgs[nPos]);
288 #endif
289 		}
290 		else // direct way
291 		{
292 		  pUnoArgs[nPos] = *(void **)pCppStack;
293 #ifdef BRDEBUG
294 	fprintf(stderr,"cpp2uno_call:direct,pUnoArgs[%d]=%p\n",nPos,pUnoArgs[nPos]);
295 #endif
296 		  // no longer needed
297 		  TYPELIB_DANGER_RELEASE( pParamTypeDescr );
298 		}
299 	  }
300 	}
301 #ifdef BRDEBUG
302 	fprintf(stderr,"cpp2uno_call2,%p,unoargs=%p\n",pThis->getUnoI()->pDispatcher,pUnoArgs);
303 #endif
304 
305 	// ExceptionHolder
306 	uno_Any aUnoExc; // Any will be constructed by callee
307 	uno_Any * pUnoExc = &aUnoExc;
308 
309 	// invoke uno dispatch call
310 	(*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
311 #ifdef BRDEBUG
312 	fprintf(stderr,"cpp2uno_call2,after dispatch\n");
313 #endif
314 
315 	// in case an exception occured...
316 	if (pUnoExc)
317 	{
318 	  // destruct temporary in/inout params
319 	  for ( ; nTempIndizes--; )
320 	  {
321 		sal_Int32 nIndex = pTempIndizes[nTempIndizes];
322 
323 		if (pParams[nIndex].bIn) // is in/inout => was constructed
324 		  uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
325 		TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
326 	  }
327 	  if (pReturnTypeDescr)
328 		TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
329 
330 	  CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() );
331 	  // has to destruct the any
332 	  // is here for dummy
333 	  return typelib_TypeClass_VOID;
334 	}
335 	else // else no exception occured...
336 	{
337 	  // temporary params
338 	  for ( ; nTempIndizes--; )
339 	  {
340 		sal_Int32 nIndex = pTempIndizes[nTempIndizes];
341 		typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
342 
343 		if (pParams[nIndex].bOut) // inout/out
344 		{
345 		  // convert and assign
346 		  uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
347 		  uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
348 			  pThis->getBridge()->getUno2Cpp() );
349 		}
350 		// destroy temp uno param
351 		uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
352 
353 		TYPELIB_DANGER_RELEASE( pParamTypeDescr );
354 	  }
355 	  // return
356 	  if (pCppReturn) // has complex return
357 	  {
358 		if (pUnoReturn != pCppReturn) // needs reconversion
359 		{
360 		  uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
361 			  pThis->getBridge()->getUno2Cpp() );
362 		  // destroy temp uno return
363 		  uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
364 		}
365 		// complex return ptr is set to return reg
366 		*(void **)pRegisterReturn = pCppReturn;
367 	  }
368 	  if (pReturnTypeDescr)
369 	  {
370 		typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
371 		TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
372 		return eRet;
373 	  }
374 	  else
375 		return typelib_TypeClass_VOID;
376 	}
377   }
378 
379 
380   //==================================================================================================
381   static typelib_TypeClass cpp_mediate(
382 	  sal_Int32 nFunctionIndex,
383 	  sal_Int32 nVtableOffset,
384 	  void ** gpreg, void ** fpreg, void ** ovrflw,
385 	  sal_Int64 * pRegisterReturn /* space for register return */ )
386   {
387 	OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
388 
389 #ifdef BRDEBUG
390 	fprintf(stderr,"cpp_mediate1 gp=%p,fp=%p,ov=%p\n",gpreg,fpreg,ovrflw);
391 	fprintf(stderr,"gp=%x,%x,%x,%x\n",gpreg[0],gpreg[1],gpreg[2],gpreg[3]);
392 #endif
393 
394 	// gpreg:  [ret *], this, [other gpr params]
395 	// fpreg:  [fpr params]
396 	// ovrflw: [gpr or fpr params (properly aligned)]
397 
398 	void * pThis;
399 	if (nFunctionIndex & 0x80000000 )
400 	{
401 	  nFunctionIndex &= 0x7fffffff;
402 	  pThis = gpreg[1];
403 	}
404 	else
405 	{
406 	  pThis = gpreg[0];
407 	}
408 #ifdef BRDEBUG
409 	fprintf(stderr,"cpp_mediate12,pThis=%p, nFunctionIndex=%d,nVtableOffset=%d\n",pThis,nFunctionIndex,nVtableOffset);
410 #endif
411 
412 	pThis = static_cast< char * >(pThis) - nVtableOffset;
413 	bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
414 	  = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
415 		  pThis);
416 #ifdef BRDEBUG
417 	fprintf(stderr,"cpp_mediate13,pCppI=%p\n",pCppI);
418 #endif
419 
420 	typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
421 
422 #ifdef BRDEBUG
423 	fprintf(stderr,"cpp_mediate2\n");
424 #endif
425 	OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
426 	if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
427 	{
428 	  throw RuntimeException(
429 		  rtl::OUString::createFromAscii("illegal vtable index!"),
430 		  (XInterface *)pThis );
431 	}
432 
433 	// determine called method
434 	sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
435 	OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
436 
437 	TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
438 
439 #ifdef BRDEBUG
440 	fprintf(stderr,"cpp_mediate3\n");
441 	OString cstr( OUStringToOString( aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
442 	fprintf( stderr, "calling %s, nFunctionIndex=%d\n", cstr.getStr(), nFunctionIndex );
443 #endif
444 	typelib_TypeClass eRet;
445 	switch (aMemberDescr.get()->eTypeClass)
446 	{
447 	  case typelib_TypeClass_INTERFACE_ATTRIBUTE:
448 		{
449 #ifdef BRDEBUG
450 	fprintf(stderr,"cpp_mediate4\n");
451 #endif
452 		  if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
453 		  {
454 			// is GET method
455 			eRet = cpp2uno_call(
456 				pCppI, aMemberDescr.get(),
457 				((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
458 				0, 0, // no params
459 				gpreg, fpreg, ovrflw, pRegisterReturn );
460 		  }
461 		  else
462 		  {
463 			// is SET method
464 			typelib_MethodParameter aParam;
465 			aParam.pTypeRef =
466 			  ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
467 			aParam.bIn		= sal_True;
468 			aParam.bOut		= sal_False;
469 
470 			eRet = cpp2uno_call(
471 				pCppI, aMemberDescr.get(),
472 				0, // indicates void return
473 				1, &aParam,
474 				gpreg, fpreg, ovrflw, pRegisterReturn );
475 		  }
476 		  break;
477 		}
478 	  case typelib_TypeClass_INTERFACE_METHOD:
479 		{
480 #ifdef BRDEBUG
481 	fprintf(stderr,"cpp_mediate5\n");
482 #endif
483 		  // is METHOD
484 		  switch (nFunctionIndex)
485 		  {
486 			case 1: // acquire()
487 			  pCppI->acquireProxy(); // non virtual call!
488 			  eRet = typelib_TypeClass_VOID;
489 			  break;
490 			case 2: // release()
491 #ifdef BRDEBUG
492 	fprintf(stderr,"cpp_mediate51\n");
493 #endif
494 			  pCppI->releaseProxy(); // non virtual call!
495 			  eRet = typelib_TypeClass_VOID;
496 #ifdef BRDEBUG
497 	fprintf(stderr,"cpp_mediate52\n");
498 #endif
499 			  break;
500 			case 0: // queryInterface() opt
501 			  {
502 				typelib_TypeDescription * pTD = 0;
503 				TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() );
504 				if (pTD)
505 				{
506 				  XInterface * pInterface = 0;
507 				  (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
508 																			 pCppI->getBridge()->getCppEnv(),
509 																			 (void **)&pInterface, pCppI->getOid().pData,
510 																			 (typelib_InterfaceTypeDescription *)pTD );
511 
512 				  if (pInterface)
513 				  {
514 					::uno_any_construct(
515 						reinterpret_cast< uno_Any * >( gpreg[0] ),
516 						&pInterface, pTD, cpp_acquire );
517 					pInterface->release();
518 					TYPELIB_DANGER_RELEASE( pTD );
519 					*(void **)pRegisterReturn = gpreg[0];
520 					eRet = typelib_TypeClass_ANY;
521 					break;
522 				  }
523 				  TYPELIB_DANGER_RELEASE( pTD );
524 				}
525 			  } // else perform queryInterface()
526 			default:
527 			  eRet = cpp2uno_call(
528 				  pCppI, aMemberDescr.get(),
529 				  ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
530 				  ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
531 				  ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
532 				  gpreg, fpreg, ovrflw, pRegisterReturn );
533 		  }
534 		  break;
535 		}
536 	  default:
537 		{
538 #ifdef BRDEBUG
539 	fprintf(stderr,"cpp_mediate6\n");
540 #endif
541 		  throw RuntimeException(
542 			  rtl::OUString::createFromAscii("no member description found!"),
543 			  (XInterface *)pThis );
544 		  // is here for dummy
545 		  eRet = typelib_TypeClass_VOID;
546 		}
547 	}
548 
549 	return eRet;
550   }
551 
552   //==================================================================================================
553   /**
554    * is called on incoming vtable calls
555    * (called by asm snippets)
556    */
557 //  static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** fpregptr, void** ovrflw)
558 //  static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** ovrflw)
559   static void cpp_vtable_call(void)
560   {
561 	int nFunctionIndex;
562 	int vTableOffset;
563 	void** pCallStack;
564 	void** ovrflw;
565 
566 	sal_Int32     gpreg[4];
567 	double        fpreg[2];
568 
569 	//memcpy( fpreg, fpregptr, 16);
570 
571 	volatile long nRegReturn[2];
572 
573 	__asm__( "sw $4, %0\n\t"
574 		 "sw $5, %1\n\t"
575 		 "sw $6, %2\n\t"
576 		 "sw $7, %3\n\t"
577 			::"m"(nFunctionIndex), "m"(vTableOffset), "m"(pCallStack), "m"(ovrflw) );
578 
579 	memcpy( gpreg, pCallStack, 16);
580 
581 #ifdef BRDEBUG
582 	fprintf(stderr,"in cpp_vtable_call nFunctionIndex is %d\n",nFunctionIndex);
583 	fprintf(stderr,"in cpp_vtable_call nVtableOffset is %d\n",vTableOffset);
584 	fprintf(stderr,"gp=%x,%x,%x,%x\n",gpreg[0],gpreg[1],gpreg[2],gpreg[3]);
585 #endif
586 
587 	//sal_Bool bComplex = nFunctionIndex & 0x80000000 ? sal_True : sal_False;
588 
589 	typelib_TypeClass aType =
590 	  cpp_mediate( nFunctionIndex, vTableOffset, (void**)gpreg, (void**)fpreg, ovrflw, (sal_Int64*)nRegReturn );
591 
592 	switch( aType )
593 	{
594 
595 	  // move return value into register space
596 	  // (will be loaded by machine code snippet)
597 
598 	  case typelib_TypeClass_BOOLEAN:
599 	  case typelib_TypeClass_BYTE:
600 		__asm__( "lbu $2,%0\n\t" : :
601 			"m"(nRegReturn[0]) );
602 		break;
603 
604 	  case typelib_TypeClass_CHAR:
605 	  case typelib_TypeClass_UNSIGNED_SHORT:
606 		__asm__( "lhu $2,%0\n\t" : :
607 			"m"(nRegReturn[0]) );
608 		break;
609 
610 	  case typelib_TypeClass_SHORT:
611 		__asm__( "lh $2,%0\n\t" : :
612 			"m"(nRegReturn[0]) );
613 		break;
614 
615 
616 	  case typelib_TypeClass_FLOAT:
617 		__asm__( "lwc1 $f0,%0\n\t" : :
618 			"m" (*((float*)nRegReturn)) );
619 		break;
620 
621 	  case typelib_TypeClass_DOUBLE:
622 	  	{ register double dret asm("$f0");
623 		dret = (*((double*)nRegReturn)); }
624 		break;
625 
626 	  case typelib_TypeClass_HYPER:
627 	  case typelib_TypeClass_UNSIGNED_HYPER:
628 		__asm__( "lw $3,%0\n\t" : :
629 			"m"(nRegReturn[1]) );  // fall through
630 
631 	  default:
632 		__asm__( "lw $2,%0\n\t" : :
633 			"m"(nRegReturn[0]) );
634 		break;
635 	}
636   }
637 
638 
639   int const codeSnippetSize = 56;
640 
641   unsigned char *  codeSnippet( unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
642 	  bool simpleRetType)
643   {
644 
645 #ifdef BRDEBUG
646 	 fprintf(stderr,"in codeSnippet functionIndex is %d\n", functionIndex);
647 	 fprintf(stderr,"in codeSnippet vtableOffset is %d\n", vtableOffset);
648 	 fflush(stderr);
649 #endif
650 
651 	if (! simpleRetType )
652 	  functionIndex |= 0x80000000;
653 
654 	unsigned long * p = (unsigned long *) code;
655 
656 	// OSL_ASSERT( sizeof (long) == 4 );
657 	OSL_ASSERT((((unsigned long)code) & 0x3) == 0 );  //aligned to 4 otherwise a mistake
658 
659 	/* generate this code */
660 	/*
661 	   #save regs into argument space required by mips abi
662             c:   afa40000        sw      a0,0(sp)
663 	   10:   afa50004        sw      a1,4(sp)
664 	   14:   afa60008        sw      a2,8(sp)
665 	   18:   afa7000c        sw      a3,12(sp)
666        #a0=index
667 	   1c:   3c040000        lui     a0,0x0
668 	   20:   34840000        ori     a0,a0,0x0
669        #a1=offset
670 	   24:   3c050000        lui     a1,0x0
671 	   28:   34a50000        ori     a1,a1,0x0
672        #a2=gpregptr
673 	   2c:   27a60000        addiu   a2,sp,0
674        #a3=ovrflw
675 	   30:   27a70010        addiu   a3,sp,16
676        #load cpp_vtable_call addr
677 	   34:   3c190000        lui     t9,0x0
678 	   38:   37390000        ori     t9,t9,0
679        #jmp to the function,note: we don't use jalr, that will destroy $ra
680        #but be sure to use t9! gp calculation depends on it
681 	   3c:   03200008        jr      t9
682 	   40:   00000000        nop
683 
684        be careful, we use the argument space reserved by the caller to
685 	   write down regs. This can avoid the need to make use of arbitary far away
686 	   stack space or to allocate a function frame for this code snippet itself.
687 	   Since only functions with variable arguments will overwrite the space,
688 	   cpp_vtable_call should be safe.
689 	   ??? gcc seems change this behavior! cpp_vtable_call overwrite the space!
690 	 */
691 
692 	* p++ = 0xafa40000;
693 	* p++ = 0xafa50004;
694 	* p++ = 0xafa60008;
695 	* p++ = 0xafa7000c;
696 	* p++ = 0x3c040000 | ((functionIndex>>16) & 0x0000ffff);
697 	* p++ = 0x34840000 | (functionIndex & 0x0000ffff);
698 	* p++ = 0x3c050000 | ((vtableOffset>>16) & 0x0000ffff);
699 	* p++ = 0x34a50000 | (vtableOffset & 0x0000ffff);
700 	* p++ = 0x27a60000;
701 	* p++ = 0x27a70010;
702 	* p++ = 0x3c190000 | ((((unsigned long)cpp_vtable_call) >> 16) & 0x0000ffff);
703 	* p++ = 0x37390000 | (((unsigned long)cpp_vtable_call) & 0x0000FFFF);
704 	* p++ = 0x03200008;
705 	* p++ = 0x00000000;
706 	return (code + codeSnippetSize);
707 
708   }
709 
710 
711 }
712 
713 
714 #define MIN_LINE_SIZE 32
715 
716 void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * /*bptr*/, unsigned char const * /*eptr*/)
717 {
718   sysmips(FLUSH_CACHE,0,0,0);
719 }
720 
721 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
722 
723 bridges::cpp_uno::shared::VtableFactory::Slot *
724 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
725 {
726     return static_cast< Slot * >(block) + 2;
727 }
728 
729 
730 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
731     sal_Int32 slotCount)
732 {
733     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
734 }
735 
736 bridges::cpp_uno::shared::VtableFactory::Slot *
737 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
738     void * block, sal_Int32 slotCount)
739 {
740     Slot * slots = mapBlockToVtable(block);
741     slots[-2].fn = 0; //null
742     slots[-1].fn = 0; //destructor
743     return slots + slotCount;
744 }
745 
746 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
747 	Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff,
748 	typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
749 	sal_Int32 functionCount, sal_Int32 vtableOffset)
750 {
751    (*slots) -= functionCount;
752     Slot * s = *slots;
753 #ifdef BRDEBUG
754    fprintf(stderr, "in addLocalFunctions functionOffset is %d\n",functionOffset);
755    fprintf(stderr, "in addLocalFunctions vtableOffset is %d\n",vtableOffset);
756    fprintf(stderr, "nMembers=%d\n",type->nMembers);
757    fflush(stderr);
758 #endif
759 
760   for (sal_Int32 i = 0; i < type->nMembers; ++i) {
761 	typelib_TypeDescription * member = 0;
762 	TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
763 	OSL_ASSERT(member != 0);
764 	switch (member->eTypeClass) {
765 	  case typelib_TypeClass_INTERFACE_ATTRIBUTE:
766 		// Getter:
767 		(s++)->fn = code + writetoexecdiff;
768 		code = codeSnippet(
769 			code, functionOffset++, vtableOffset,
770 			bridges::cpp_uno::shared::isSimpleType(
771 			  reinterpret_cast<
772 			  typelib_InterfaceAttributeTypeDescription * >(
773 				member)->pAttributeTypeRef));
774 
775 		// Setter:
776 		if (!reinterpret_cast<
777 			typelib_InterfaceAttributeTypeDescription * >(
778 			  member)->bReadOnly)
779 		{
780 		  (s++)->fn = code + writetoexecdiff;
781 		  code = codeSnippet(code, functionOffset++, vtableOffset, true);
782 		}
783 		break;
784 
785 	  case typelib_TypeClass_INTERFACE_METHOD:
786 		(s++)->fn = code + writetoexecdiff;
787 		code = codeSnippet(
788 			code, functionOffset++, vtableOffset,
789 			bridges::cpp_uno::shared::isSimpleType(
790 			  reinterpret_cast<
791 			  typelib_InterfaceMethodTypeDescription * >(
792 				member)->pReturnTypeRef));
793 		break;
794 
795 	  default:
796 		OSL_ASSERT(false);
797 		break;
798 	}
799 	TYPELIB_DANGER_RELEASE(member);
800   }
801   return code;
802 }
803 
804