Bump for 3.6-28
[LibreOffice.git] / bridges / source / cpp_uno / gcc3_linux_mips / cpp2uno.cxx
bloba275312369bd1a305fa286098a9a52cb7a68b55f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
28 #include <com/sun/star/uno/genfunc.hxx>
29 #include <typelib/typedescription.hxx>
30 #include <uno/data.h>
31 #include <osl/endian.h>
32 #include "bridges/cpp_uno/shared/bridge.hxx"
33 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
34 #include "bridges/cpp_uno/shared/types.hxx"
35 #include "bridges/cpp_uno/shared/vtablefactory.hxx"
36 #include "share.hxx"
38 #include <stdio.h>
39 #include <string.h>
41 using namespace com::sun::star::uno;
43 //#define BRDEBUG
45 #ifdef BRDEBUG
46 #include <rtl/strbuf.hxx>
47 #include <rtl/ustrbuf.hxx>
48 #include <osl/diagnose.h>
49 #include <osl/mutex.hxx>
50 using namespace ::std;
51 using namespace ::osl;
52 using namespace ::rtl;
53 #endif
54 #include <sys/sysmips.h>
56 #ifdef OSL_BIGENDIAN
57 #define IS_BIG_ENDIAN 1
58 #else
59 #define IS_BIG_ENDIAN 0
60 #endif
62 using namespace ::com::sun::star::uno;
64 namespace
67 //==================================================================================================
68 static typelib_TypeClass cpp2uno_call(
69 bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
70 const typelib_TypeDescription * pMemberTypeDescr,
71 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
72 sal_Int32 nParams, typelib_MethodParameter * pParams,
73 void ** gpreg, void ** /*fpreg*/, void ** ovrflw,
74 sal_Int64 * pRegisterReturn /* space for register return */ )
76 /* Most MIPS ABIs view the arguments as a struct, of which the
77 first N words go in registers and the rest go on the stack. If I < N, the
78 Ith word might go in Ith integer argument register or the Ith
79 floating-point one. For these ABIs, we only need to remember the number
80 of words passed so far. We are interested only in o32 ABI,so it is the
81 case.
83 int nw = 0; // number of words used by arguments
85 #ifdef BRDEBUG
86 fprintf(stderr,"cpp2uno_call1\n");
87 #endif
89 /* C++ has [ret *] or this as the first arguments, so no arguments will
90 * be passed in floating-point registers?
92 //int int_seen = 0; // have we seen integer arguments?
94 void ** pCppStack; //temporary stack pointer
96 // gpreg: [ret *], this, [gpr params]
97 // fpreg: [fpr params]
98 // ovrflw: [gpr or fpr params (properly aligned)]
100 // return
101 typelib_TypeDescription * pReturnTypeDescr = 0;
102 if (pReturnTypeRef)
103 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
105 void * pUnoReturn = 0;
106 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
108 if (pReturnTypeDescr)
110 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
112 pUnoReturn = pRegisterReturn; // direct way for simple types
113 #ifdef BRDEBUG
114 fprintf(stderr,"cpp2uno_call:simplereturn\n");
115 #endif
117 else // complex return via ptr (pCppReturn)
119 pCppReturn = *(void **)gpreg;
120 gpreg++;
121 nw++;
123 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
124 ? alloca( pReturnTypeDescr->nSize )
125 : pCppReturn); // direct way
126 #ifdef BRDEBUG
127 fprintf(stderr,"cpp2uno_call:complexreturn\n");
128 #endif
132 // pop this
133 gpreg++;
134 nw++;
136 // stack space
137 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
138 // parameters
139 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
140 void ** pCppArgs = pUnoArgs + nParams;
141 // indizes of values this have to be converted (interface conversion cpp<=>uno)
142 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
143 // type descriptions for reconversions
144 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
146 sal_Int32 nTempIndizes = 0;
148 #ifdef BRDEBUG
149 fprintf(stderr,"cpp2uno_call:nParams=%d\n",nParams);
150 #endif
152 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
154 const typelib_MethodParameter & rParam = pParams[nPos];
155 typelib_TypeDescription * pParamTypeDescr = 0;
156 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
158 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
159 // value
162 switch (pParamTypeDescr->eTypeClass)
164 case typelib_TypeClass_DOUBLE:
165 case typelib_TypeClass_HYPER:
166 case typelib_TypeClass_UNSIGNED_HYPER:
167 #ifdef BRDEBUG
168 fprintf(stderr,"cpp2uno_call:hyper=%d,%p\n",pParamTypeDescr->eTypeClass,gpreg[0]);
169 #endif
170 if (nw < 3) {
171 if (nw & 1) {
172 nw++;
173 gpreg++;
175 #ifdef BRDEBUG
176 fprintf(stderr,"cpp2uno_call:gpreg=%p,%p\n",gpreg[0],gpreg[1]);
177 #endif
178 pCppArgs[nPos] = gpreg;
179 pUnoArgs[nPos] = gpreg;
180 nw += 2;
181 gpreg += 2;
182 } else {
183 if (((long)ovrflw) & 4) ovrflw++;
184 #ifdef BRDEBUG
185 fprintf(stderr,"cpp2uno_call:overflw=%p,%p\n",ovrflw[0],ovrflw[1]);
186 #endif
187 pCppArgs[nPos] = ovrflw;
188 pUnoArgs[nPos] = ovrflw;
189 ovrflw += 2;
191 break;
193 case typelib_TypeClass_BYTE:
194 case typelib_TypeClass_BOOLEAN:
195 #ifdef BRDEBUG
196 fprintf(stderr,"cpp2uno_call:byte=%p,%p\n",gpreg[0],ovrflw[0]);
197 #endif
198 if (nw < 4) {
199 pCppArgs[nPos] = ((char *)gpreg + 3*IS_BIG_ENDIAN);
200 pUnoArgs[nPos] = ((char *)gpreg + 3*IS_BIG_ENDIAN);
201 nw++;
202 gpreg++;
203 } else {
204 pCppArgs[nPos] = ((char *)ovrflw + 3*IS_BIG_ENDIAN);
205 pUnoArgs[nPos] = ((char *)ovrflw + 3*IS_BIG_ENDIAN);
206 ovrflw++;
208 break;
211 case typelib_TypeClass_CHAR:
212 case typelib_TypeClass_SHORT:
213 case typelib_TypeClass_UNSIGNED_SHORT:
214 #ifdef BRDEBUG
215 fprintf(stderr,"cpp2uno_call:char=%p,%p\n",gpreg[0],ovrflw[0]);
216 #endif
217 if (nw < 4) {
218 pCppArgs[nPos] = ((char *)gpreg + 2*IS_BIG_ENDIAN);
219 pUnoArgs[nPos] = ((char *)gpreg + 2*IS_BIG_ENDIAN);
220 nw++;
221 gpreg++;
222 } else {
223 pCppArgs[nPos] = ((char *)ovrflw + 2*IS_BIG_ENDIAN);
224 pUnoArgs[nPos] = ((char *)ovrflw + 2*IS_BIG_ENDIAN);
225 ovrflw++;
227 break;
230 default:
231 #ifdef BRDEBUG
232 fprintf(stderr,"cpp2uno_call:def=%p,%p\n",gpreg[0],ovrflw[0]);
233 #endif
234 if (nw < 4) {
235 pCppArgs[nPos] = gpreg;
236 pUnoArgs[nPos] = gpreg;
237 nw++;
238 gpreg++;
239 } else {
240 pCppArgs[nPos] = ovrflw;
241 pUnoArgs[nPos] = ovrflw;
242 ovrflw++;
244 break;
247 // no longer needed
248 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
250 else // ptr to complex value | ref
253 #ifdef BRDEBUG
254 fprintf(stderr,"cpp2uno_call:ptr|ref\n");
255 #endif
256 if (nw < 4) {
257 pCppArgs[nPos] = *(void **)gpreg;
258 pCppStack = gpreg;
259 nw++;
260 gpreg++;
261 } else {
262 pCppArgs[nPos] = *(void **)ovrflw;
263 pCppStack = ovrflw;
264 ovrflw++;
266 #ifdef BRDEBUG
267 fprintf(stderr,"cpp2uno_call:pCppStack=%p\n",pCppStack);
268 #endif
270 if (! rParam.bIn) // is pure out
272 // uno out is unconstructed mem!
273 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
274 pTempIndizes[nTempIndizes] = nPos;
275 // will be released at reconversion
276 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
278 // is in/inout
279 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
281 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
282 *(void **)pCppStack, pParamTypeDescr,
283 pThis->getBridge()->getCpp2Uno() );
284 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
285 // will be released at reconversion
286 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
287 #ifdef BRDEBUG
288 fprintf(stderr,"cpp2uno_call:related to interface,%p,%d,pUnoargs[%d]=%p\n",*(void**)pCppStack,pParamTypeDescr->nSize,nPos,pUnoArgs[nPos]);
289 #endif
291 else // direct way
293 pUnoArgs[nPos] = *(void **)pCppStack;
294 #ifdef BRDEBUG
295 fprintf(stderr,"cpp2uno_call:direct,pUnoArgs[%d]=%p\n",nPos,pUnoArgs[nPos]);
296 #endif
297 // no longer needed
298 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
302 #ifdef BRDEBUG
303 fprintf(stderr,"cpp2uno_call2,%p,unoargs=%p\n",pThis->getUnoI()->pDispatcher,pUnoArgs);
304 #endif
306 // ExceptionHolder
307 uno_Any aUnoExc; // Any will be constructed by callee
308 uno_Any * pUnoExc = &aUnoExc;
310 // invoke uno dispatch call
311 (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
312 #ifdef BRDEBUG
313 fprintf(stderr,"cpp2uno_call2,after dispatch\n");
314 #endif
316 // in case an exception occurred...
317 if (pUnoExc)
319 // destruct temporary in/inout params
320 for ( ; nTempIndizes--; )
322 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
324 if (pParams[nIndex].bIn) // is in/inout => was constructed
325 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
326 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
328 if (pReturnTypeDescr)
329 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
331 CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() );
332 // has to destruct the any
333 // is here for dummy
334 return typelib_TypeClass_VOID;
336 else // else no exception occurred...
338 // temporary params
339 for ( ; nTempIndizes--; )
341 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
342 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
344 if (pParams[nIndex].bOut) // inout/out
346 // convert and assign
347 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
348 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
349 pThis->getBridge()->getUno2Cpp() );
351 // destroy temp uno param
352 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
354 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
356 // return
357 if (pCppReturn) // has complex return
359 if (pUnoReturn != pCppReturn) // needs reconversion
361 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
362 pThis->getBridge()->getUno2Cpp() );
363 // destroy temp uno return
364 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
366 // complex return ptr is set to return reg
367 *(void **)pRegisterReturn = pCppReturn;
369 if (pReturnTypeDescr)
371 typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
372 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
373 return eRet;
375 else
376 return typelib_TypeClass_VOID;
381 //==================================================================================================
382 static typelib_TypeClass cpp_mediate(
383 sal_Int32 nFunctionIndex,
384 sal_Int32 nVtableOffset,
385 void ** gpreg, void ** fpreg, void ** ovrflw,
386 sal_Int64 * pRegisterReturn /* space for register return */ )
388 OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
390 #ifdef BRDEBUG
391 fprintf(stderr,"cpp_mediate1 gp=%p,fp=%p,ov=%p\n",gpreg,fpreg,ovrflw);
392 fprintf(stderr,"gp=%x,%x,%x,%x\n",gpreg[0],gpreg[1],gpreg[2],gpreg[3]);
393 #endif
395 // gpreg: [ret *], this, [other gpr params]
396 // fpreg: [fpr params]
397 // ovrflw: [gpr or fpr params (properly aligned)]
399 void * pThis;
400 if (nFunctionIndex & 0x80000000 )
402 nFunctionIndex &= 0x7fffffff;
403 pThis = gpreg[1];
405 else
407 pThis = gpreg[0];
409 #ifdef BRDEBUG
410 fprintf(stderr,"cpp_mediate12,pThis=%p, nFunctionIndex=%d,nVtableOffset=%d\n",pThis,nFunctionIndex,nVtableOffset);
411 #endif
413 pThis = static_cast< char * >(pThis) - nVtableOffset;
414 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
415 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
416 pThis);
417 #ifdef BRDEBUG
418 fprintf(stderr,"cpp_mediate13,pCppI=%p\n",pCppI);
419 #endif
421 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
423 #ifdef BRDEBUG
424 fprintf(stderr,"cpp_mediate2\n");
425 #endif
426 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
427 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
429 throw RuntimeException(
430 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )),
431 (XInterface *)pThis );
434 // determine called method
435 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
436 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
438 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
440 #ifdef BRDEBUG
441 fprintf(stderr,"cpp_mediate3\n");
442 OString cstr( OUStringToOString( aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
443 fprintf( stderr, "calling %s, nFunctionIndex=%d\n", cstr.getStr(), nFunctionIndex );
444 #endif
445 typelib_TypeClass eRet;
446 switch (aMemberDescr.get()->eTypeClass)
448 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
450 #ifdef BRDEBUG
451 fprintf(stderr,"cpp_mediate4\n");
452 #endif
453 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
455 // is GET method
456 eRet = cpp2uno_call(
457 pCppI, aMemberDescr.get(),
458 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
459 0, 0, // no params
460 gpreg, fpreg, ovrflw, pRegisterReturn );
462 else
464 // is SET method
465 typelib_MethodParameter aParam;
466 aParam.pTypeRef =
467 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
468 aParam.bIn = sal_True;
469 aParam.bOut = sal_False;
471 eRet = cpp2uno_call(
472 pCppI, aMemberDescr.get(),
473 0, // indicates void return
474 1, &aParam,
475 gpreg, fpreg, ovrflw, pRegisterReturn );
477 break;
479 case typelib_TypeClass_INTERFACE_METHOD:
481 #ifdef BRDEBUG
482 fprintf(stderr,"cpp_mediate5\n");
483 #endif
484 // is METHOD
485 switch (nFunctionIndex)
487 case 1: // acquire()
488 pCppI->acquireProxy(); // non virtual call!
489 eRet = typelib_TypeClass_VOID;
490 break;
491 case 2: // release()
492 #ifdef BRDEBUG
493 fprintf(stderr,"cpp_mediate51\n");
494 #endif
495 pCppI->releaseProxy(); // non virtual call!
496 eRet = typelib_TypeClass_VOID;
497 #ifdef BRDEBUG
498 fprintf(stderr,"cpp_mediate52\n");
499 #endif
500 break;
501 case 0: // queryInterface() opt
503 typelib_TypeDescription * pTD = 0;
504 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() );
505 if (pTD)
507 XInterface * pInterface = 0;
508 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
509 pCppI->getBridge()->getCppEnv(),
510 (void **)&pInterface, pCppI->getOid().pData,
511 (typelib_InterfaceTypeDescription *)pTD );
513 if (pInterface)
515 ::uno_any_construct(
516 reinterpret_cast< uno_Any * >( gpreg[0] ),
517 &pInterface, pTD, cpp_acquire );
518 pInterface->release();
519 TYPELIB_DANGER_RELEASE( pTD );
520 *(void **)pRegisterReturn = gpreg[0];
521 eRet = typelib_TypeClass_ANY;
522 break;
524 TYPELIB_DANGER_RELEASE( pTD );
526 } // else perform queryInterface()
527 default:
528 eRet = cpp2uno_call(
529 pCppI, aMemberDescr.get(),
530 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
531 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
532 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
533 gpreg, fpreg, ovrflw, pRegisterReturn );
535 break;
537 default:
539 #ifdef BRDEBUG
540 fprintf(stderr,"cpp_mediate6\n");
541 #endif
542 throw RuntimeException(
543 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )),
544 (XInterface *)pThis );
548 return eRet;
551 //==================================================================================================
553 * is called on incoming vtable calls
554 * (called by asm snippets)
556 // static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** fpregptr, void** ovrflw)
557 // static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** ovrflw)
558 static void cpp_vtable_call(void)
560 int nFunctionIndex;
561 int vTableOffset;
562 void** pCallStack;
563 void** ovrflw;
565 sal_Int32 gpreg[4];
566 double fpreg[2];
568 //memcpy( fpreg, fpregptr, 16);
570 volatile long nRegReturn[2];
572 __asm__( "sw $4, %0\n\t"
573 "sw $5, %1\n\t"
574 "sw $6, %2\n\t"
575 "sw $7, %3\n\t"
576 ::"m"(nFunctionIndex), "m"(vTableOffset), "m"(pCallStack), "m"(ovrflw) );
578 memcpy( gpreg, pCallStack, 16);
580 #ifdef BRDEBUG
581 fprintf(stderr,"in cpp_vtable_call nFunctionIndex is %d\n",nFunctionIndex);
582 fprintf(stderr,"in cpp_vtable_call nVtableOffset is %d\n",vTableOffset);
583 fprintf(stderr,"gp=%x,%x,%x,%x\n",gpreg[0],gpreg[1],gpreg[2],gpreg[3]);
584 #endif
586 //sal_Bool bComplex = nFunctionIndex & 0x80000000 ? sal_True : sal_False;
588 typelib_TypeClass aType =
589 cpp_mediate( nFunctionIndex, vTableOffset, (void**)gpreg, (void**)fpreg, ovrflw, (sal_Int64*)nRegReturn );
591 switch( aType )
594 // move return value into register space
595 // (will be loaded by machine code snippet)
597 case typelib_TypeClass_BOOLEAN:
598 case typelib_TypeClass_BYTE:
599 __asm__( "lbu $2,%0\n\t" : :
600 "m"(nRegReturn[0]) );
601 break;
603 case typelib_TypeClass_CHAR:
604 case typelib_TypeClass_UNSIGNED_SHORT:
605 __asm__( "lhu $2,%0\n\t" : :
606 "m"(nRegReturn[0]) );
607 break;
609 case typelib_TypeClass_SHORT:
610 __asm__( "lh $2,%0\n\t" : :
611 "m"(nRegReturn[0]) );
612 break;
615 case typelib_TypeClass_FLOAT:
616 __asm__( "lwc1 $f0,%0\n\t" : :
617 "m" (*((float*)nRegReturn)) );
618 break;
620 case typelib_TypeClass_DOUBLE:
621 { register double dret asm("$f0");
622 dret = (*((double*)nRegReturn)); }
623 break;
625 case typelib_TypeClass_HYPER:
626 case typelib_TypeClass_UNSIGNED_HYPER:
627 __asm__( "lw $3,%0\n\t" : :
628 "m"(nRegReturn[1]) ); // fall through
630 default:
631 __asm__( "lw $2,%0\n\t" : :
632 "m"(nRegReturn[0]) );
633 break;
638 int const codeSnippetSize = 56;
640 unsigned char * codeSnippet( unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
641 bool simpleRetType)
644 #ifdef BRDEBUG
645 fprintf(stderr,"in codeSnippet functionIndex is %d\n", functionIndex);
646 fprintf(stderr,"in codeSnippet vtableOffset is %d\n", vtableOffset);
647 fflush(stderr);
648 #endif
650 if (! simpleRetType )
651 functionIndex |= 0x80000000;
653 unsigned long * p = (unsigned long *) code;
655 // OSL_ASSERT( sizeof (long) == 4 );
656 OSL_ASSERT((((unsigned long)code) & 0x3) == 0 ); //aligned to 4 otherwise a mistake
658 /* generate this code */
660 #save regs into argument space required by mips abi
661 c: afa40000 sw a0,0(sp)
662 10: afa50004 sw a1,4(sp)
663 14: afa60008 sw a2,8(sp)
664 18: afa7000c sw a3,12(sp)
665 #a0=index
666 1c: 3c040000 lui a0,0x0
667 20: 34840000 ori a0,a0,0x0
668 #a1=offset
669 24: 3c050000 lui a1,0x0
670 28: 34a50000 ori a1,a1,0x0
671 #a2=gpregptr
672 2c: 27a60000 addiu a2,sp,0
673 #a3=ovrflw
674 30: 27a70010 addiu a3,sp,16
675 #load cpp_vtable_call addr
676 34: 3c190000 lui t9,0x0
677 38: 37390000 ori t9,t9,0
678 #jmp to the function,note: we don't use jalr, that will destroy $ra
679 #but be sure to use t9! gp calculation depends on it
680 3c: 03200008 jr t9
681 40: 00000000 nop
683 be careful, we use the argument space reserved by the caller to
684 write down regs. This can avoid the need to make use of arbitary far away
685 stack space or to allocate a function frame for this code snippet itself.
686 Since only functions with variable arguments will overwrite the space,
687 cpp_vtable_call should be safe.
688 ??? gcc seems change this behavior! cpp_vtable_call overwrite the space!
691 * p++ = 0xafa40000;
692 * p++ = 0xafa50004;
693 * p++ = 0xafa60008;
694 * p++ = 0xafa7000c;
695 * p++ = 0x3c040000 | ((functionIndex>>16) & 0x0000ffff);
696 * p++ = 0x34840000 | (functionIndex & 0x0000ffff);
697 * p++ = 0x3c050000 | ((vtableOffset>>16) & 0x0000ffff);
698 * p++ = 0x34a50000 | (vtableOffset & 0x0000ffff);
699 * p++ = 0x27a60000;
700 * p++ = 0x27a70010;
701 * p++ = 0x3c190000 | ((((unsigned long)cpp_vtable_call) >> 16) & 0x0000ffff);
702 * p++ = 0x37390000 | (((unsigned long)cpp_vtable_call) & 0x0000FFFF);
703 * p++ = 0x03200008;
704 * p++ = 0x00000000;
705 return (code + codeSnippetSize);
713 #define MIN_LINE_SIZE 32
715 void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * /*bptr*/, unsigned char const * /*eptr*/)
717 sysmips(FLUSH_CACHE,0,0,0);
720 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
722 bridges::cpp_uno::shared::VtableFactory::Slot *
723 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
725 return static_cast< Slot * >(block) + 2;
729 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
730 sal_Int32 slotCount)
732 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
735 bridges::cpp_uno::shared::VtableFactory::Slot *
736 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
737 void * block, sal_Int32 slotCount)
739 Slot * slots = mapBlockToVtable(block);
740 slots[-2].fn = 0; //null
741 slots[-1].fn = 0; //destructor
742 return slots + slotCount;
745 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
746 Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff,
747 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
748 sal_Int32 functionCount, sal_Int32 vtableOffset)
750 (*slots) -= functionCount;
751 Slot * s = *slots;
752 #ifdef BRDEBUG
753 fprintf(stderr, "in addLocalFunctions functionOffset is %d\n",functionOffset);
754 fprintf(stderr, "in addLocalFunctions vtableOffset is %d\n",vtableOffset);
755 fprintf(stderr, "nMembers=%d\n",type->nMembers);
756 fflush(stderr);
757 #endif
759 for (sal_Int32 i = 0; i < type->nMembers; ++i) {
760 typelib_TypeDescription * member = 0;
761 TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
762 OSL_ASSERT(member != 0);
763 switch (member->eTypeClass) {
764 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
765 // Getter:
766 (s++)->fn = code + writetoexecdiff;
767 code = codeSnippet(
768 code, functionOffset++, vtableOffset,
769 bridges::cpp_uno::shared::isSimpleType(
770 reinterpret_cast<
771 typelib_InterfaceAttributeTypeDescription * >(
772 member)->pAttributeTypeRef));
774 // Setter:
775 if (!reinterpret_cast<
776 typelib_InterfaceAttributeTypeDescription * >(
777 member)->bReadOnly)
779 (s++)->fn = code + writetoexecdiff;
780 code = codeSnippet(code, functionOffset++, vtableOffset, true);
782 break;
784 case typelib_TypeClass_INTERFACE_METHOD:
785 (s++)->fn = code + writetoexecdiff;
786 code = codeSnippet(
787 code, functionOffset++, vtableOffset,
788 bridges::cpp_uno::shared::isSimpleType(
789 reinterpret_cast<
790 typelib_InterfaceMethodTypeDescription * >(
791 member)->pReturnTypeRef));
792 break;
794 default:
795 OSL_ASSERT(false);
796 break;
798 TYPELIB_DANGER_RELEASE(member);
800 return code;
803 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */