merge the formfield patch from ooo-build
[ooovba.git] / bridges / source / cpp_uno / gcc3_linux_mips / cpp2uno.cxx
blobe7a0e6e11583a8cb5c40842f5e50150b2768cb31
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cpp2uno.cxx,v $
10 * $Revision: 1.6 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 #include <com/sun/star/uno/genfunc.hxx>
31 #include <typelib/typedescription.hxx>
32 #include <uno/data.h>
33 #include <osl/endian.h>
34 #include "bridges/cpp_uno/shared/bridge.hxx"
35 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
36 #include "bridges/cpp_uno/shared/types.hxx"
37 #include "bridges/cpp_uno/shared/vtablefactory.hxx"
38 #include "share.hxx"
40 #include <stdio.h>
41 #include <string.h>
43 using namespace com::sun::star::uno;
45 //#define BRDEBUG
47 #ifdef BRDEBUG
48 #include <rtl/strbuf.hxx>
49 #include <rtl/ustrbuf.hxx>
50 #include <osl/diagnose.h>
51 #include <osl/mutex.hxx>
52 using namespace ::std;
53 using namespace ::osl;
54 using namespace ::rtl;
55 #endif
56 #include <sys/sysmips.h>
58 #ifdef OSL_BIGENDIAN
59 #define IS_BIG_ENDIAN 1
60 #else
61 #define IS_BIG_ENDIAN 0
62 #endif
64 using namespace ::com::sun::star::uno;
66 namespace
69 //==================================================================================================
70 static typelib_TypeClass cpp2uno_call(
71 bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
72 const typelib_TypeDescription * pMemberTypeDescr,
73 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
74 sal_Int32 nParams, typelib_MethodParameter * pParams,
75 void ** gpreg, void ** /*fpreg*/, void ** ovrflw,
76 sal_Int64 * pRegisterReturn /* space for register return */ )
78 /* Most MIPS ABIs view the arguments as a struct, of which the
79 first N words go in registers and the rest go on the stack. If I < N, the
80 Ith word might go in Ith integer argument register or the Ith
81 floating-point one. For these ABIs, we only need to remember the number
82 of words passed so far. We are interested only in o32 ABI,so it is the
83 case.
85 int nw = 0; // number of words used by arguments
87 #ifdef BRDEBUG
88 fprintf(stderr,"cpp2uno_call1\n");
89 #endif
91 /* C++ has [ret *] or this as the first arguments, so no arguments will
92 * be passed in floating-point registers?
94 //int int_seen = 0; // have we seen integer arguments?
96 void ** pCppStack; //temporary stack pointer
98 // gpreg: [ret *], this, [gpr params]
99 // fpreg: [fpr params]
100 // ovrflw: [gpr or fpr params (properly aligned)]
102 // return
103 typelib_TypeDescription * pReturnTypeDescr = 0;
104 if (pReturnTypeRef)
105 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
107 void * pUnoReturn = 0;
108 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
110 if (pReturnTypeDescr)
112 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
114 pUnoReturn = pRegisterReturn; // direct way for simple types
115 #ifdef BRDEBUG
116 fprintf(stderr,"cpp2uno_call:simplereturn\n");
117 #endif
119 else // complex return via ptr (pCppReturn)
121 pCppReturn = *(void **)gpreg;
122 gpreg++;
123 nw++;
125 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
126 ? alloca( pReturnTypeDescr->nSize )
127 : pCppReturn); // direct way
128 #ifdef BRDEBUG
129 fprintf(stderr,"cpp2uno_call:complexreturn\n");
130 #endif
134 // pop this
135 gpreg++;
136 nw++;
138 // stack space
139 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
140 // parameters
141 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
142 void ** pCppArgs = pUnoArgs + nParams;
143 // indizes of values this have to be converted (interface conversion cpp<=>uno)
144 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
145 // type descriptions for reconversions
146 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
148 sal_Int32 nTempIndizes = 0;
150 #ifdef BRDEBUG
151 fprintf(stderr,"cpp2uno_call:nParams=%d\n",nParams);
152 #endif
154 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
156 const typelib_MethodParameter & rParam = pParams[nPos];
157 typelib_TypeDescription * pParamTypeDescr = 0;
158 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
160 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
161 // value
164 switch (pParamTypeDescr->eTypeClass)
166 case typelib_TypeClass_DOUBLE:
167 case typelib_TypeClass_HYPER:
168 case typelib_TypeClass_UNSIGNED_HYPER:
169 #ifdef BRDEBUG
170 fprintf(stderr,"cpp2uno_call:hyper=%d,%p\n",pParamTypeDescr->eTypeClass,gpreg[0]);
171 #endif
172 if (nw < 3) {
173 if (nw & 1) {
174 nw++;
175 gpreg++;
177 #ifdef BRDEBUG
178 fprintf(stderr,"cpp2uno_call:gpreg=%p,%p\n",gpreg[0],gpreg[1]);
179 #endif
180 pCppArgs[nPos] = gpreg;
181 pUnoArgs[nPos] = gpreg;
182 nw += 2;
183 gpreg += 2;
184 } else {
185 if (((long)ovrflw) & 4) ovrflw++;
186 #ifdef BRDEBUG
187 fprintf(stderr,"cpp2uno_call:overflw=%p,%p\n",ovrflw[0],ovrflw[1]);
188 #endif
189 pCppArgs[nPos] = ovrflw;
190 pUnoArgs[nPos] = ovrflw;
191 ovrflw += 2;
193 break;
195 case typelib_TypeClass_BYTE:
196 case typelib_TypeClass_BOOLEAN:
197 #ifdef BRDEBUG
198 fprintf(stderr,"cpp2uno_call:byte=%p,%p\n",gpreg[0],ovrflw[0]);
199 #endif
200 if (nw < 4) {
201 pCppArgs[nPos] = ((char *)gpreg + 3*IS_BIG_ENDIAN);
202 pUnoArgs[nPos] = ((char *)gpreg + 3*IS_BIG_ENDIAN);
203 nw++;
204 gpreg++;
205 } else {
206 pCppArgs[nPos] = ((char *)ovrflw + 3*IS_BIG_ENDIAN);
207 pUnoArgs[nPos] = ((char *)ovrflw + 3*IS_BIG_ENDIAN);
208 ovrflw++;
210 break;
213 case typelib_TypeClass_CHAR:
214 case typelib_TypeClass_SHORT:
215 case typelib_TypeClass_UNSIGNED_SHORT:
216 #ifdef BRDEBUG
217 fprintf(stderr,"cpp2uno_call:char=%p,%p\n",gpreg[0],ovrflw[0]);
218 #endif
219 if (nw < 4) {
220 pCppArgs[nPos] = ((char *)gpreg + 2*IS_BIG_ENDIAN);
221 pUnoArgs[nPos] = ((char *)gpreg + 2*IS_BIG_ENDIAN);
222 nw++;
223 gpreg++;
224 } else {
225 pCppArgs[nPos] = ((char *)ovrflw + 2*IS_BIG_ENDIAN);
226 pUnoArgs[nPos] = ((char *)ovrflw + 2*IS_BIG_ENDIAN);
227 ovrflw++;
229 break;
232 default:
233 #ifdef BRDEBUG
234 fprintf(stderr,"cpp2uno_call:def=%p,%p\n",gpreg[0],ovrflw[0]);
235 #endif
236 if (nw < 4) {
237 pCppArgs[nPos] = gpreg;
238 pUnoArgs[nPos] = gpreg;
239 nw++;
240 gpreg++;
241 } else {
242 pCppArgs[nPos] = ovrflw;
243 pUnoArgs[nPos] = ovrflw;
244 ovrflw++;
246 break;
249 // no longer needed
250 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
252 else // ptr to complex value | ref
255 #ifdef BRDEBUG
256 fprintf(stderr,"cpp2uno_call:ptr|ref\n");
257 #endif
258 if (nw < 4) {
259 pCppArgs[nPos] = *(void **)gpreg;
260 pCppStack = gpreg;
261 nw++;
262 gpreg++;
263 } else {
264 pCppArgs[nPos] = *(void **)ovrflw;
265 pCppStack = ovrflw;
266 ovrflw++;
268 #ifdef BRDEBUG
269 fprintf(stderr,"cpp2uno_call:pCppStack=%p\n",pCppStack);
270 #endif
272 if (! rParam.bIn) // is pure out
274 // uno out is unconstructed mem!
275 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
276 pTempIndizes[nTempIndizes] = nPos;
277 // will be released at reconversion
278 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
280 // is in/inout
281 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
283 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
284 *(void **)pCppStack, pParamTypeDescr,
285 pThis->getBridge()->getCpp2Uno() );
286 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
287 // will be released at reconversion
288 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
289 #ifdef BRDEBUG
290 fprintf(stderr,"cpp2uno_call:related to interface,%p,%d,pUnoargs[%d]=%p\n",*(void**)pCppStack,pParamTypeDescr->nSize,nPos,pUnoArgs[nPos]);
291 #endif
293 else // direct way
295 pUnoArgs[nPos] = *(void **)pCppStack;
296 #ifdef BRDEBUG
297 fprintf(stderr,"cpp2uno_call:direct,pUnoArgs[%d]=%p\n",nPos,pUnoArgs[nPos]);
298 #endif
299 // no longer needed
300 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
304 #ifdef BRDEBUG
305 fprintf(stderr,"cpp2uno_call2,%p,unoargs=%p\n",pThis->getUnoI()->pDispatcher,pUnoArgs);
306 #endif
308 // ExceptionHolder
309 uno_Any aUnoExc; // Any will be constructed by callee
310 uno_Any * pUnoExc = &aUnoExc;
312 // invoke uno dispatch call
313 (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
314 #ifdef BRDEBUG
315 fprintf(stderr,"cpp2uno_call2,after dispatch\n");
316 #endif
318 // in case an exception occured...
319 if (pUnoExc)
321 // destruct temporary in/inout params
322 for ( ; nTempIndizes--; )
324 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
326 if (pParams[nIndex].bIn) // is in/inout => was constructed
327 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
328 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
330 if (pReturnTypeDescr)
331 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
333 CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() );
334 // has to destruct the any
335 // is here for dummy
336 return typelib_TypeClass_VOID;
338 else // else no exception occured...
340 // temporary params
341 for ( ; nTempIndizes--; )
343 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
344 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
346 if (pParams[nIndex].bOut) // inout/out
348 // convert and assign
349 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
350 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
351 pThis->getBridge()->getUno2Cpp() );
353 // destroy temp uno param
354 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
356 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
358 // return
359 if (pCppReturn) // has complex return
361 if (pUnoReturn != pCppReturn) // needs reconversion
363 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
364 pThis->getBridge()->getUno2Cpp() );
365 // destroy temp uno return
366 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
368 // complex return ptr is set to return reg
369 *(void **)pRegisterReturn = pCppReturn;
371 if (pReturnTypeDescr)
373 typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
374 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
375 return eRet;
377 else
378 return typelib_TypeClass_VOID;
383 //==================================================================================================
384 static typelib_TypeClass cpp_mediate(
385 sal_Int32 nFunctionIndex,
386 sal_Int32 nVtableOffset,
387 void ** gpreg, void ** fpreg, void ** ovrflw,
388 sal_Int64 * pRegisterReturn /* space for register return */ )
390 OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
392 #ifdef BRDEBUG
393 fprintf(stderr,"cpp_mediate1 gp=%p,fp=%p,ov=%p\n",gpreg,fpreg,ovrflw);
394 fprintf(stderr,"gp=%x,%x,%x,%x\n",gpreg[0],gpreg[1],gpreg[2],gpreg[3]);
395 #endif
397 // gpreg: [ret *], this, [other gpr params]
398 // fpreg: [fpr params]
399 // ovrflw: [gpr or fpr params (properly aligned)]
401 void * pThis;
402 if (nFunctionIndex & 0x80000000 )
404 nFunctionIndex &= 0x7fffffff;
405 pThis = gpreg[1];
407 else
409 pThis = gpreg[0];
411 #ifdef BRDEBUG
412 fprintf(stderr,"cpp_mediate12,pThis=%p, nFunctionIndex=%d,nVtableOffset=%d\n",pThis,nFunctionIndex,nVtableOffset);
413 #endif
415 pThis = static_cast< char * >(pThis) - nVtableOffset;
416 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
417 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
418 pThis);
419 #ifdef BRDEBUG
420 fprintf(stderr,"cpp_mediate13,pCppI=%p\n",pCppI);
421 #endif
423 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
425 #ifdef BRDEBUG
426 fprintf(stderr,"cpp_mediate2\n");
427 #endif
428 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
429 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
431 throw RuntimeException(
432 rtl::OUString::createFromAscii("illegal vtable index!"),
433 (XInterface *)pThis );
436 // determine called method
437 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
438 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
440 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
442 #ifdef BRDEBUG
443 fprintf(stderr,"cpp_mediate3\n");
444 OString cstr( OUStringToOString( aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
445 fprintf( stderr, "calling %s, nFunctionIndex=%d\n", cstr.getStr(), nFunctionIndex );
446 #endif
447 typelib_TypeClass eRet;
448 switch (aMemberDescr.get()->eTypeClass)
450 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
452 #ifdef BRDEBUG
453 fprintf(stderr,"cpp_mediate4\n");
454 #endif
455 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
457 // is GET method
458 eRet = cpp2uno_call(
459 pCppI, aMemberDescr.get(),
460 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
461 0, 0, // no params
462 gpreg, fpreg, ovrflw, pRegisterReturn );
464 else
466 // is SET method
467 typelib_MethodParameter aParam;
468 aParam.pTypeRef =
469 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
470 aParam.bIn = sal_True;
471 aParam.bOut = sal_False;
473 eRet = cpp2uno_call(
474 pCppI, aMemberDescr.get(),
475 0, // indicates void return
476 1, &aParam,
477 gpreg, fpreg, ovrflw, pRegisterReturn );
479 break;
481 case typelib_TypeClass_INTERFACE_METHOD:
483 #ifdef BRDEBUG
484 fprintf(stderr,"cpp_mediate5\n");
485 #endif
486 // is METHOD
487 switch (nFunctionIndex)
489 case 1: // acquire()
490 pCppI->acquireProxy(); // non virtual call!
491 eRet = typelib_TypeClass_VOID;
492 break;
493 case 2: // release()
494 #ifdef BRDEBUG
495 fprintf(stderr,"cpp_mediate51\n");
496 #endif
497 pCppI->releaseProxy(); // non virtual call!
498 eRet = typelib_TypeClass_VOID;
499 #ifdef BRDEBUG
500 fprintf(stderr,"cpp_mediate52\n");
501 #endif
502 break;
503 case 0: // queryInterface() opt
505 typelib_TypeDescription * pTD = 0;
506 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() );
507 if (pTD)
509 XInterface * pInterface = 0;
510 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
511 pCppI->getBridge()->getCppEnv(),
512 (void **)&pInterface, pCppI->getOid().pData,
513 (typelib_InterfaceTypeDescription *)pTD );
515 if (pInterface)
517 ::uno_any_construct(
518 reinterpret_cast< uno_Any * >( gpreg[0] ),
519 &pInterface, pTD, cpp_acquire );
520 pInterface->release();
521 TYPELIB_DANGER_RELEASE( pTD );
522 *(void **)pRegisterReturn = gpreg[0];
523 eRet = typelib_TypeClass_ANY;
524 break;
526 TYPELIB_DANGER_RELEASE( pTD );
528 } // else perform queryInterface()
529 default:
530 eRet = cpp2uno_call(
531 pCppI, aMemberDescr.get(),
532 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
533 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
534 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
535 gpreg, fpreg, ovrflw, pRegisterReturn );
537 break;
539 default:
541 #ifdef BRDEBUG
542 fprintf(stderr,"cpp_mediate6\n");
543 #endif
544 throw RuntimeException(
545 rtl::OUString::createFromAscii("no member description found!"),
546 (XInterface *)pThis );
547 // is here for dummy
548 eRet = typelib_TypeClass_VOID;
552 return eRet;
555 //==================================================================================================
557 * is called on incoming vtable calls
558 * (called by asm snippets)
560 // static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** fpregptr, void** ovrflw)
561 // static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** ovrflw)
562 static void cpp_vtable_call(void)
564 int nFunctionIndex;
565 int vTableOffset;
566 void** pCallStack;
567 void** ovrflw;
569 sal_Int32 gpreg[4];
570 double fpreg[2];
572 //memcpy( fpreg, fpregptr, 16);
574 volatile long nRegReturn[2];
576 __asm__( "sw $4, %0\n\t"
577 "sw $5, %1\n\t"
578 "sw $6, %2\n\t"
579 "sw $7, %3\n\t"
580 ::"m"(nFunctionIndex), "m"(vTableOffset), "m"(pCallStack), "m"(ovrflw) );
582 memcpy( gpreg, pCallStack, 16);
584 #ifdef BRDEBUG
585 fprintf(stderr,"in cpp_vtable_call nFunctionIndex is %d\n",nFunctionIndex);
586 fprintf(stderr,"in cpp_vtable_call nVtableOffset is %d\n",vTableOffset);
587 fprintf(stderr,"gp=%x,%x,%x,%x\n",gpreg[0],gpreg[1],gpreg[2],gpreg[3]);
588 #endif
590 //sal_Bool bComplex = nFunctionIndex & 0x80000000 ? sal_True : sal_False;
592 typelib_TypeClass aType =
593 cpp_mediate( nFunctionIndex, vTableOffset, (void**)gpreg, (void**)fpreg, ovrflw, (sal_Int64*)nRegReturn );
595 switch( aType )
598 // move return value into register space
599 // (will be loaded by machine code snippet)
601 case typelib_TypeClass_BOOLEAN:
602 case typelib_TypeClass_BYTE:
603 __asm__( "lbu $2,%0\n\t" : :
604 "m"(nRegReturn[0]) );
605 break;
607 case typelib_TypeClass_CHAR:
608 case typelib_TypeClass_UNSIGNED_SHORT:
609 __asm__( "lhu $2,%0\n\t" : :
610 "m"(nRegReturn[0]) );
611 break;
613 case typelib_TypeClass_SHORT:
614 __asm__( "lh $2,%0\n\t" : :
615 "m"(nRegReturn[0]) );
616 break;
619 case typelib_TypeClass_FLOAT:
620 __asm__( "lwc1 $f0,%0\n\t" : :
621 "m" (*((float*)nRegReturn)) );
622 break;
624 case typelib_TypeClass_DOUBLE:
625 { register double dret asm("$f0");
626 dret = (*((double*)nRegReturn)); }
627 break;
629 case typelib_TypeClass_HYPER:
630 case typelib_TypeClass_UNSIGNED_HYPER:
631 __asm__( "lw $3,%0\n\t" : :
632 "m"(nRegReturn[1]) ); // fall through
634 default:
635 __asm__( "lw $2,%0\n\t" : :
636 "m"(nRegReturn[0]) );
637 break;
642 int const codeSnippetSize = 56;
644 unsigned char * codeSnippet( unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
645 bool simpleRetType)
648 #ifdef BRDEBUG
649 fprintf(stderr,"in codeSnippet functionIndex is %d\n", functionIndex);
650 fprintf(stderr,"in codeSnippet vtableOffset is %d\n", vtableOffset);
651 fflush(stderr);
652 #endif
654 if (! simpleRetType )
655 functionIndex |= 0x80000000;
657 unsigned long * p = (unsigned long *) code;
659 // OSL_ASSERT( sizeof (long) == 4 );
660 OSL_ASSERT((((unsigned long)code) & 0x3) == 0 ); //aligned to 4 otherwise a mistake
662 /* generate this code */
664 #save regs into argument space required by mips abi
665 c: afa40000 sw a0,0(sp)
666 10: afa50004 sw a1,4(sp)
667 14: afa60008 sw a2,8(sp)
668 18: afa7000c sw a3,12(sp)
669 #a0=index
670 1c: 3c040000 lui a0,0x0
671 20: 34840000 ori a0,a0,0x0
672 #a1=offset
673 24: 3c050000 lui a1,0x0
674 28: 34a50000 ori a1,a1,0x0
675 #a2=gpregptr
676 2c: 27a60000 addiu a2,sp,0
677 #a3=ovrflw
678 30: 27a70010 addiu a3,sp,16
679 #load cpp_vtable_call addr
680 34: 3c190000 lui t9,0x0
681 38: 37390000 ori t9,t9,0
682 #jmp to the function,note: we don't use jalr, that will destroy $ra
683 #but be sure to use t9! gp calculation depends on it
684 3c: 03200008 jr t9
685 40: 00000000 nop
687 be careful, we use the argument space reserved by the caller to
688 write down regs. This can avoid the need to make use of arbitary far away
689 stack space or to allocate a function frame for this code snippet itself.
690 Since only functions with variable arguments will overwrite the space,
691 cpp_vtable_call should be safe.
692 ??? gcc seems change this behavior! cpp_vtable_call overwrite the space!
695 * p++ = 0xafa40000;
696 * p++ = 0xafa50004;
697 * p++ = 0xafa60008;
698 * p++ = 0xafa7000c;
699 * p++ = 0x3c040000 | ((functionIndex>>16) & 0x0000ffff);
700 * p++ = 0x34840000 | (functionIndex & 0x0000ffff);
701 * p++ = 0x3c050000 | ((vtableOffset>>16) & 0x0000ffff);
702 * p++ = 0x34a50000 | (vtableOffset & 0x0000ffff);
703 * p++ = 0x27a60000;
704 * p++ = 0x27a70010;
705 * p++ = 0x3c190000 | ((((unsigned long)cpp_vtable_call) >> 16) & 0x0000ffff);
706 * p++ = 0x37390000 | (((unsigned long)cpp_vtable_call) & 0x0000FFFF);
707 * p++ = 0x03200008;
708 * p++ = 0x00000000;
709 return (code + codeSnippetSize);
717 #define MIN_LINE_SIZE 32
719 void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * /*bptr*/, unsigned char const * /*eptr*/)
721 sysmips(FLUSH_CACHE,0,0,0);
724 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
726 bridges::cpp_uno::shared::VtableFactory::Slot *
727 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
729 return static_cast< Slot * >(block) + 2;
733 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
734 sal_Int32 slotCount)
736 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
739 bridges::cpp_uno::shared::VtableFactory::Slot *
740 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
741 void * block, sal_Int32 slotCount)
743 Slot * slots = mapBlockToVtable(block);
744 slots[-2].fn = 0; //null
745 slots[-1].fn = 0; //destructor
746 return slots + slotCount;
749 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
750 Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff,
751 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
752 sal_Int32 functionCount, sal_Int32 vtableOffset)
754 (*slots) -= functionCount;
755 Slot * s = *slots;
756 #ifdef BRDEBUG
757 fprintf(stderr, "in addLocalFunctions functionOffset is %d\n",functionOffset);
758 fprintf(stderr, "in addLocalFunctions vtableOffset is %d\n",vtableOffset);
759 fprintf(stderr, "nMembers=%d\n",type->nMembers);
760 fflush(stderr);
761 #endif
763 for (sal_Int32 i = 0; i < type->nMembers; ++i) {
764 typelib_TypeDescription * member = 0;
765 TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
766 OSL_ASSERT(member != 0);
767 switch (member->eTypeClass) {
768 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
769 // Getter:
770 (s++)->fn = code + writetoexecdiff;
771 code = codeSnippet(
772 code, functionOffset++, vtableOffset,
773 bridges::cpp_uno::shared::isSimpleType(
774 reinterpret_cast<
775 typelib_InterfaceAttributeTypeDescription * >(
776 member)->pAttributeTypeRef));
778 // Setter:
779 if (!reinterpret_cast<
780 typelib_InterfaceAttributeTypeDescription * >(
781 member)->bReadOnly)
783 (s++)->fn = code + writetoexecdiff;
784 code = codeSnippet(code, functionOffset++, vtableOffset, true);
786 break;
788 case typelib_TypeClass_INTERFACE_METHOD:
789 (s++)->fn = code + writetoexecdiff;
790 code = codeSnippet(
791 code, functionOffset++, vtableOffset,
792 bridges::cpp_uno::shared::isSimpleType(
793 reinterpret_cast<
794 typelib_InterfaceMethodTypeDescription * >(
795 member)->pReturnTypeRef));
796 break;
798 default:
799 OSL_ASSERT(false);
800 break;
802 TYPELIB_DANGER_RELEASE(member);
804 return code;