tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / bridges / source / cpp_uno / gcc3_linux_mips / cpp2uno.cxx
blob21ec313942ac9fa4d6313e1b891b5369bfaef312
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #include <com/sun/star/uno/genfunc.hxx>
20 #include <sal/log.hxx>
21 #include <typelib/typedescription.hxx>
22 #include <uno/data.h>
23 #include <osl/endian.h>
24 #include "bridge.hxx"
25 #include "cppinterfaceproxy.hxx"
26 #include "types.hxx"
27 #include "vtablefactory.hxx"
28 #include "share.hxx"
30 #include <stdio.h>
31 #include <string.h>
32 #include <typeinfo>
34 using namespace com::sun::star::uno;
36 //#define BRDEBUG
38 #ifdef BRDEBUG
39 #include <rtl/strbuf.hxx>
40 #include <rtl/ustrbuf.hxx>
41 using namespace ::std;
42 using namespace ::osl;
43 using namespace ::rtl;
44 #endif
46 #ifndef ANDROID
47 #include <sys/sysmips.h>
48 #endif
50 #ifdef ANDROID
51 #include <unistd.h>
52 #endif
54 #ifdef OSL_BIGENDIAN
55 #define IS_BIG_ENDIAN 1
56 #else
57 #define IS_BIG_ENDIAN 0
58 #endif
60 namespace
63 static typelib_TypeClass cpp2uno_call(
64 bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
65 const typelib_TypeDescription * pMemberTypeDescr,
66 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
67 sal_Int32 nParams, typelib_MethodParameter * pParams,
68 void ** gpreg, void ** /*fpreg*/, void ** ovrflw,
69 sal_Int64 * pRegisterReturn /* space for register return */ )
71 /* Most MIPS ABIs view the arguments as a struct, of which the
72 first N words go in registers and the rest go on the stack. If I < N, the
73 Ith word might go in Ith integer argument register or the Ith
74 floating-point one. For these ABIs, we only need to remember the number
75 of words passed so far. We are interested only in o32 ABI,so it is the
76 case.
78 int nw = 0; // number of words used by arguments
80 #ifdef BRDEBUG
81 fprintf(stderr,"cpp2uno_call1\n");
82 #endif
84 /* C++ has [ret *] or this as the first arguments, so no arguments will
85 * be passed in floating-point registers?
87 //int int_seen = 0; // have we seen integer arguments?
89 void ** pCppStack; //temporary stack pointer
91 // gpreg: [ret *], this, [gpr params]
92 // fpreg: [fpr params]
93 // ovrflw: [gpr or fpr params (properly aligned)]
95 // return
96 typelib_TypeDescription * pReturnTypeDescr = 0;
97 if (pReturnTypeRef)
98 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
100 void * pUnoReturn = 0;
101 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
103 if (pReturnTypeDescr)
105 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
107 pUnoReturn = pRegisterReturn; // direct way for simple types
108 #ifdef BRDEBUG
109 fprintf(stderr,"cpp2uno_call:simplereturn\n");
110 #endif
112 else // complex return via ptr (pCppReturn)
114 pCppReturn = *(void **)gpreg;
115 gpreg++;
116 nw++;
118 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
119 ? alloca( pReturnTypeDescr->nSize )
120 : pCppReturn); // direct way
121 #ifdef BRDEBUG
122 fprintf(stderr,"cpp2uno_call:complexreturn\n");
123 #endif
127 // pop this
128 gpreg++;
129 nw++;
131 // stack space
132 static_assert(sizeof(void *) == sizeof(sal_Int32), "### unexpected size!");
133 // parameters
134 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
135 void ** pCppArgs = pUnoArgs + nParams;
136 // indices of values this have to be converted (interface conversion cpp<=>uno)
137 sal_Int32 * pTempIndices = (sal_Int32 *)(pUnoArgs + (2 * nParams));
138 // type descriptions for reconversions
139 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
141 sal_Int32 nTempIndices = 0;
143 #ifdef BRDEBUG
144 fprintf(stderr,"cpp2uno_call:nParams=%d\n",nParams);
145 #endif
147 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
149 const typelib_MethodParameter & rParam = pParams[nPos];
150 typelib_TypeDescription * pParamTypeDescr = 0;
151 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
153 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
154 // value
157 switch (pParamTypeDescr->eTypeClass)
159 case typelib_TypeClass_DOUBLE:
160 case typelib_TypeClass_HYPER:
161 case typelib_TypeClass_UNSIGNED_HYPER:
162 #ifdef BRDEBUG
163 fprintf(stderr,"cpp2uno_call:hyper=%d,%p\n",pParamTypeDescr->eTypeClass,gpreg[0]);
164 #endif
165 if (nw < 3) {
166 if (nw & 1) {
167 nw++;
168 gpreg++;
170 #ifdef BRDEBUG
171 fprintf(stderr,"cpp2uno_call:gpreg=%p,%p\n",gpreg[0],gpreg[1]);
172 #endif
173 pCppArgs[nPos] = gpreg;
174 pUnoArgs[nPos] = gpreg;
175 nw += 2;
176 gpreg += 2;
177 } else {
178 if (((long)ovrflw) & 4) ovrflw++;
179 #ifdef BRDEBUG
180 fprintf(stderr,"cpp2uno_call:overflw=%p,%p\n",ovrflw[0],ovrflw[1]);
181 #endif
182 pCppArgs[nPos] = ovrflw;
183 pUnoArgs[nPos] = ovrflw;
184 ovrflw += 2;
186 break;
188 case typelib_TypeClass_BYTE:
189 case typelib_TypeClass_BOOLEAN:
190 #ifdef BRDEBUG
191 fprintf(stderr,"cpp2uno_call:byte=%p,%p\n",gpreg[0],ovrflw[0]);
192 #endif
193 if (nw < 4) {
194 pCppArgs[nPos] = ((char *)gpreg + 3*IS_BIG_ENDIAN);
195 pUnoArgs[nPos] = ((char *)gpreg + 3*IS_BIG_ENDIAN);
196 nw++;
197 gpreg++;
198 } else {
199 pCppArgs[nPos] = ((char *)ovrflw + 3*IS_BIG_ENDIAN);
200 pUnoArgs[nPos] = ((char *)ovrflw + 3*IS_BIG_ENDIAN);
201 ovrflw++;
203 break;
206 case typelib_TypeClass_CHAR:
207 case typelib_TypeClass_SHORT:
208 case typelib_TypeClass_UNSIGNED_SHORT:
209 #ifdef BRDEBUG
210 fprintf(stderr,"cpp2uno_call:char=%p,%p\n",gpreg[0],ovrflw[0]);
211 #endif
212 if (nw < 4) {
213 pCppArgs[nPos] = ((char *)gpreg + 2*IS_BIG_ENDIAN);
214 pUnoArgs[nPos] = ((char *)gpreg + 2*IS_BIG_ENDIAN);
215 nw++;
216 gpreg++;
217 } else {
218 pCppArgs[nPos] = ((char *)ovrflw + 2*IS_BIG_ENDIAN);
219 pUnoArgs[nPos] = ((char *)ovrflw + 2*IS_BIG_ENDIAN);
220 ovrflw++;
222 break;
225 default:
226 #ifdef BRDEBUG
227 fprintf(stderr,"cpp2uno_call:def=%p,%p\n",gpreg[0],ovrflw[0]);
228 #endif
229 if (nw < 4) {
230 pCppArgs[nPos] = gpreg;
231 pUnoArgs[nPos] = gpreg;
232 nw++;
233 gpreg++;
234 } else {
235 pCppArgs[nPos] = ovrflw;
236 pUnoArgs[nPos] = ovrflw;
237 ovrflw++;
239 break;
242 // no longer needed
243 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
245 else // ptr to complex value | ref
248 #ifdef BRDEBUG
249 fprintf(stderr,"cpp2uno_call:ptr|ref\n");
250 #endif
251 if (nw < 4) {
252 pCppArgs[nPos] = *(void **)gpreg;
253 pCppStack = gpreg;
254 nw++;
255 gpreg++;
256 } else {
257 pCppArgs[nPos] = *(void **)ovrflw;
258 pCppStack = ovrflw;
259 ovrflw++;
261 #ifdef BRDEBUG
262 fprintf(stderr,"cpp2uno_call:pCppStack=%p\n",pCppStack);
263 #endif
265 if (! rParam.bIn) // is pure out
267 // uno out is unconstructed mem!
268 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
269 pTempIndices[nTempIndices] = nPos;
270 // will be released at reconversion
271 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
273 // is in/inout
274 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
276 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
277 *(void **)pCppStack, pParamTypeDescr,
278 pThis->getBridge()->getCpp2Uno() );
279 pTempIndices[nTempIndices] = nPos; // has to be reconverted
280 // will be released at reconversion
281 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
282 #ifdef BRDEBUG
283 fprintf(stderr,"cpp2uno_call:related to interface,%p,%d,pUnoargs[%d]=%p\n",*(void**)pCppStack,pParamTypeDescr->nSize,nPos,pUnoArgs[nPos]);
284 #endif
286 else // direct way
288 pUnoArgs[nPos] = *(void **)pCppStack;
289 #ifdef BRDEBUG
290 fprintf(stderr,"cpp2uno_call:direct,pUnoArgs[%d]=%p\n",nPos,pUnoArgs[nPos]);
291 #endif
292 // no longer needed
293 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
297 #ifdef BRDEBUG
298 fprintf(stderr,"cpp2uno_call2,%p,unoargs=%p\n",pThis->getUnoI()->pDispatcher,pUnoArgs);
299 #endif
301 // ExceptionHolder
302 uno_Any aUnoExc; // Any will be constructed by callee
303 uno_Any * pUnoExc = &aUnoExc;
305 // invoke uno dispatch call
306 (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
307 #ifdef BRDEBUG
308 fprintf(stderr,"cpp2uno_call2,after dispatch\n");
309 #endif
311 // in case an exception occurred...
312 if (pUnoExc)
314 // destruct temporary in/inout params
315 for ( ; nTempIndices--; )
317 sal_Int32 nIndex = pTempIndices[nTempIndices];
319 if (pParams[nIndex].bIn) // is in/inout => was constructed
320 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndices], 0 );
321 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
323 if (pReturnTypeDescr)
324 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
326 CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() );
327 // has to destruct the any
328 // is here for dummy
329 return typelib_TypeClass_VOID;
331 else // else no exception occurred...
333 // temporary params
334 for ( ; nTempIndices--; )
336 sal_Int32 nIndex = pTempIndices[nTempIndices];
337 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
339 if (pParams[nIndex].bOut) // inout/out
341 // convert and assign
342 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
343 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
344 pThis->getBridge()->getUno2Cpp() );
346 // destroy temp uno param
347 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
349 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
351 // return
352 if (pCppReturn) // has complex return
354 if (pUnoReturn != pCppReturn) // needs reconversion
356 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
357 pThis->getBridge()->getUno2Cpp() );
358 // destroy temp uno return
359 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
361 // complex return ptr is set to return reg
362 *(void **)pRegisterReturn = pCppReturn;
364 if (pReturnTypeDescr)
366 typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
367 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
368 return eRet;
370 else
371 return typelib_TypeClass_VOID;
376 static typelib_TypeClass cpp_mediate(
377 sal_Int32 nFunctionIndex,
378 sal_Int32 nVtableOffset,
379 void ** gpreg, void ** fpreg, void ** ovrflw,
380 sal_Int64 * pRegisterReturn /* space for register return */ )
382 static_assert(sizeof(sal_Int32)==sizeof(void *), "### unexpected!");
384 #ifdef BRDEBUG
385 fprintf(stderr,"cpp_mediate1 gp=%p,fp=%p,ov=%p\n",gpreg,fpreg,ovrflw);
386 fprintf(stderr,"gp=%p,%p,%p,%p\n",gpreg[0],gpreg[1],gpreg[2],gpreg[3]);
387 #endif
389 // gpreg: [ret *], this, [other gpr params]
390 // fpreg: [fpr params]
391 // ovrflw: [gpr or fpr params (properly aligned)]
393 void * pThis;
394 if (nFunctionIndex & 0x80000000 )
396 nFunctionIndex &= 0x7fffffff;
397 pThis = gpreg[1];
399 else
401 pThis = gpreg[0];
403 #ifdef BRDEBUG
404 fprintf(stderr,"cpp_mediate12,pThis=%p, nFunctionIndex=%d,nVtableOffset=%d\n",pThis,nFunctionIndex,nVtableOffset);
405 #endif
407 pThis = static_cast< char * >(pThis) - nVtableOffset;
408 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
409 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
410 pThis);
411 #ifdef BRDEBUG
412 fprintf(stderr,"cpp_mediate13,pCppI=%p\n",pCppI);
413 #endif
415 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
417 #ifdef BRDEBUG
418 fprintf(stderr,"cpp_mediate2\n");
419 #endif
420 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
422 SAL_WARN(
423 "bridges",
424 "illegal " << OUString::unacquired(&pTypeDescr->aBase.pTypeName)
425 << " vtable index " << nFunctionIndex << "/"
426 << pTypeDescr->nMapFunctionIndexToMemberIndex);
427 throw RuntimeException(
428 ("illegal " + OUString::unacquired(&pTypeDescr->aBase.pTypeName)
429 + " vtable index " + OUString::number(nFunctionIndex) + "/"
430 + OUString::number(pTypeDescr->nMapFunctionIndexToMemberIndex)),
431 (XInterface *)pThis);
434 // determine called method
435 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
436 assert(nMemberPos < pTypeDescr->nAllMembers);
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( "no member description found!", (XInterface *)pThis );
546 return eRet;
550 * is called on incoming vtable calls
551 * (called by asm snippets)
553 // static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** fpregptr, void** ovrflw)
554 // static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** ovrflw)
555 static void cpp_vtable_call()
557 int nFunctionIndex;
558 int vTableOffset;
559 void** pCallStack;
560 void** ovrflw;
562 sal_Int32 gpreg[4];
563 double fpreg[2];
565 //memcpy( fpreg, fpregptr, 16);
567 volatile long nRegReturn[2];
569 __asm__( "sw $4, %0\n\t"
570 "sw $5, %1\n\t"
571 "sw $6, %2\n\t"
572 "sw $7, %3\n\t"
573 ::"m"(nFunctionIndex), "m"(vTableOffset), "m"(pCallStack), "m"(ovrflw) );
575 memcpy( gpreg, pCallStack, 16);
577 #ifdef BRDEBUG
578 fprintf(stderr,"in cpp_vtable_call nFunctionIndex is %d\n",nFunctionIndex);
579 fprintf(stderr,"in cpp_vtable_call nVtableOffset is %d\n",vTableOffset);
580 fprintf(stderr,"gp=%x,%x,%x,%x\n",gpreg[0],gpreg[1],gpreg[2],gpreg[3]);
581 #endif
583 //sal_Bool bComplex = nFunctionIndex & 0x80000000 ? sal_True : sal_False;
585 typelib_TypeClass aType =
586 cpp_mediate( nFunctionIndex, vTableOffset, (void**)gpreg, (void**)fpreg, ovrflw, (sal_Int64*)nRegReturn );
588 switch( aType )
591 // move return value into register space
592 // (will be loaded by machine code snippet)
594 case typelib_TypeClass_BOOLEAN:
595 case typelib_TypeClass_BYTE:
596 __asm__( "lbu $2,%0\n\t" : :
597 "m"(nRegReturn[0]) );
598 break;
600 case typelib_TypeClass_CHAR:
601 case typelib_TypeClass_UNSIGNED_SHORT:
602 __asm__( "lhu $2,%0\n\t" : :
603 "m"(nRegReturn[0]) );
604 break;
606 case typelib_TypeClass_SHORT:
607 __asm__( "lh $2,%0\n\t" : :
608 "m"(nRegReturn[0]) );
609 break;
612 case typelib_TypeClass_FLOAT:
613 __asm__( "lwc1 $f0,%0\n\t" : :
614 "m" (*((float*)nRegReturn)) );
615 break;
617 case typelib_TypeClass_DOUBLE:
618 { register double dret asm("$f0");
619 dret = (*((double*)nRegReturn));
620 (void) dret;
622 break;
624 case typelib_TypeClass_HYPER:
625 case typelib_TypeClass_UNSIGNED_HYPER:
626 __asm__( "lw $3,%0\n\t" : :
627 "m"(nRegReturn[1]) ); // fall through
629 default:
630 __asm__( "lw $2,%0\n\t" : :
631 "m"(nRegReturn[0]) );
632 break;
637 int const codeSnippetSize = 56;
639 unsigned char * codeSnippet( unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
640 bool simpleRetType)
643 #ifdef BRDEBUG
644 fprintf(stderr,"in codeSnippet functionIndex is %d\n", functionIndex);
645 fprintf(stderr,"in codeSnippet vtableOffset is %d\n", vtableOffset);
646 fflush(stderr);
647 #endif
649 if (! simpleRetType )
650 functionIndex |= 0x80000000;
652 unsigned long * p = (unsigned long *) code;
654 // static_assert( sizeof (long) == 4 );
655 assert((((unsigned long)code) & 0x3) == 0 ); //aligned to 4 otherwise a mistake
657 /* generate this code */
659 #save regs into argument space required by mips abi
660 c: afa40000 sw a0,0(sp)
661 10: afa50004 sw a1,4(sp)
662 14: afa60008 sw a2,8(sp)
663 18: afa7000c sw a3,12(sp)
664 #a0=index
665 1c: 3c040000 lui a0,0x0
666 20: 34840000 ori a0,a0,0x0
667 #a1=offset
668 24: 3c050000 lui a1,0x0
669 28: 34a50000 ori a1,a1,0x0
670 #a2=gpregptr
671 2c: 27a60000 addiu a2,sp,0
672 #a3=ovrflw
673 30: 27a70010 addiu a3,sp,16
674 #load cpp_vtable_call addr
675 34: 3c190000 lui t9,0x0
676 38: 37390000 ori t9,t9,0
677 #jmp to the function,note: we don't use jalr, that will destroy $ra
678 #but be sure to use t9! gp calculation depends on it
679 3c: 03200008 jr t9
680 40: 00000000 nop
682 be careful, we use the argument space reserved by the caller to
683 write down regs. This can avoid the need to make use of arbitrary far away
684 stack space or to allocate a function frame for this code snippet itself.
685 Since only functions with variable arguments will overwrite the space,
686 cpp_vtable_call should be safe.
687 ??? gcc seems change this behavior! cpp_vtable_call overwrite the space!
690 * p++ = 0xafa40000;
691 * p++ = 0xafa50004;
692 * p++ = 0xafa60008;
693 * p++ = 0xafa7000c;
694 * p++ = 0x3c040000 | ((functionIndex>>16) & 0x0000ffff);
695 * p++ = 0x34840000 | (functionIndex & 0x0000ffff);
696 * p++ = 0x3c050000 | ((vtableOffset>>16) & 0x0000ffff);
697 * p++ = 0x34a50000 | (vtableOffset & 0x0000ffff);
698 * p++ = 0x27a60000;
699 * p++ = 0x27a70010;
700 * p++ = 0x3c190000 | ((((unsigned long)cpp_vtable_call) >> 16) & 0x0000ffff);
701 * p++ = 0x37390000 | (((unsigned long)cpp_vtable_call) & 0x0000FFFF);
702 * p++ = 0x03200008;
703 * p++ = 0x00000000;
704 return (code + codeSnippetSize);
712 void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const *bptr, unsigned char const *eptr)
714 #ifndef ANDROID
715 (void) bptr;
716 (void) eptr;
717 sysmips(FLUSH_CACHE,0,0,0);
718 #else
719 cacheflush((long) bptr, (long) eptr, 0);
720 #endif
723 struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
725 bridges::cpp_uno::shared::VtableFactory::Slot *
726 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
728 return static_cast< Slot * >(block) + 2;
732 std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize(
733 sal_Int32 slotCount)
735 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
738 namespace {
739 // Some dummy type whose RTTI is used in the synthesized proxy vtables to make uses of dynamic_cast
740 // on such proxy objects not crash:
741 struct ProxyRtti {};
744 bridges::cpp_uno::shared::VtableFactory::Slot *
745 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
746 void * block, sal_Int32 slotCount, sal_Int32,
747 typelib_InterfaceTypeDescription *)
749 Slot * slots = mapBlockToVtable(block);
750 slots[-2].fn = 0; //null
751 slots[-1].fn = &typeid(ProxyRtti);
752 return slots + slotCount;
755 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
756 Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff,
757 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
758 sal_Int32 functionCount, sal_Int32 vtableOffset)
760 (*slots) -= functionCount;
761 Slot * s = *slots;
762 #ifdef BRDEBUG
763 fprintf(stderr, "in addLocalFunctions functionOffset is %d\n",functionOffset);
764 fprintf(stderr, "in addLocalFunctions vtableOffset is %d\n",vtableOffset);
765 fprintf(stderr, "nMembers=%d\n",type->nMembers);
766 fflush(stderr);
767 #endif
769 for (sal_Int32 i = 0; i < type->nMembers; ++i) {
770 typelib_TypeDescription * member = 0;
771 TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
772 assert(member != 0);
773 switch (member->eTypeClass) {
774 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
775 // Getter:
776 (s++)->fn = code + writetoexecdiff;
777 code = codeSnippet(
778 code, functionOffset++, vtableOffset,
779 bridges::cpp_uno::shared::isSimpleType(
780 reinterpret_cast<
781 typelib_InterfaceAttributeTypeDescription * >(
782 member)->pAttributeTypeRef));
784 // Setter:
785 if (!reinterpret_cast<
786 typelib_InterfaceAttributeTypeDescription * >(
787 member)->bReadOnly)
789 (s++)->fn = code + writetoexecdiff;
790 code = codeSnippet(code, functionOffset++, vtableOffset, true);
792 break;
794 case typelib_TypeClass_INTERFACE_METHOD:
795 (s++)->fn = code + writetoexecdiff;
796 code = codeSnippet(
797 code, functionOffset++, vtableOffset,
798 bridges::cpp_uno::shared::isSimpleType(
799 reinterpret_cast<
800 typelib_InterfaceMethodTypeDescription * >(
801 member)->pReturnTypeRef));
802 break;
804 default:
805 assert(false);
806 break;
808 TYPELIB_DANGER_RELEASE(member);
810 return code;
813 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */