LibreOffice Module bridges (master) 1
gcc3_linux_mips/cpp2uno.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
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"
29
30#include <stdio.h>
31#include <string.h>
32#include <typeinfo>
33
34using namespace com::sun::star::uno;
35
36//#define BRDEBUG
37
38#ifdef BRDEBUG
39#include <rtl/strbuf.hxx>
40#include <rtl/ustrbuf.hxx>
41using namespace ::std;
42using namespace ::osl;
43using namespace ::rtl;
44#endif
45
46#ifndef ANDROID
47#include <sys/sysmips.h>
48#endif
49
50#ifdef ANDROID
51#include <unistd.h>
52#endif
53
54#ifdef OSL_BIGENDIAN
55#define IS_BIG_ENDIAN 1
56#else
57#define IS_BIG_ENDIAN 0
58#endif
59
60namespace
61{
62
63 static typelib_TypeClass cpp2uno_call(
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 */ )
70 {
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.
77 */
78 int nw = 0; // number of words used by arguments
79
80#ifdef BRDEBUG
81 fprintf(stderr,"cpp2uno_call1\n");
82#endif
83
84 /* C++ has [ret *] or this as the first arguments, so no arguments will
85 * be passed in floating-point registers?
86 */
87 //int int_seen = 0; // have we seen integer arguments?
88
89 void ** pCppStack; //temporary stack pointer
90
91 // gpreg: [ret *], this, [gpr params]
92 // fpreg: [fpr params]
93 // ovrflw: [gpr or fpr params (properly aligned)]
94
95 // return
96 typelib_TypeDescription * pReturnTypeDescr = 0;
97 if (pReturnTypeRef)
98 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
99
100 void * pUnoReturn = 0;
101 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
102
103 if (pReturnTypeDescr)
104 {
105 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
106 {
107 pUnoReturn = pRegisterReturn; // direct way for simple types
108#ifdef BRDEBUG
109 fprintf(stderr,"cpp2uno_call:simplereturn\n");
110#endif
111 }
112 else // complex return via ptr (pCppReturn)
113 {
114 pCppReturn = *(void **)gpreg;
115 gpreg++;
116 nw++;
117
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
124 }
125 }
126
127 // pop this
128 gpreg++;
129 nw++;
130
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));
140
141 sal_Int32 nTempIndices = 0;
142
143#ifdef BRDEBUG
144 fprintf(stderr,"cpp2uno_call:nParams=%d\n",nParams);
145#endif
146
147 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
148 {
149 const typelib_MethodParameter & rParam = pParams[nPos];
150 typelib_TypeDescription * pParamTypeDescr = 0;
151 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
152
153 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
154 // value
155 {
156
157 switch (pParamTypeDescr->eTypeClass)
158 {
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++;
169 }
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;
185 }
186 break;
187
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++;
202 }
203 break;
204
205
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++;
221 }
222 break;
223
224
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++;
238 }
239 break;
240
241 }
242 // no longer needed
243 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
244 }
245 else // ptr to complex value | ref
246 {
247
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++;
260 }
261#ifdef BRDEBUG
262 fprintf(stderr,"cpp2uno_call:pCppStack=%p\n",pCppStack);
263#endif
264
265 if (! rParam.bIn) // is pure out
266 {
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;
272 }
273 // is in/inout
274 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
275 {
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
285 }
286 else // direct way
287 {
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 );
294 }
295 }
296 }
297#ifdef BRDEBUG
298 fprintf(stderr,"cpp2uno_call2,%p,unoargs=%p\n",pThis->getUnoI()->pDispatcher,pUnoArgs);
299#endif
300
301 // ExceptionHolder
302 uno_Any aUnoExc; // Any will be constructed by callee
303 uno_Any * pUnoExc = &aUnoExc;
304
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
310
311 // in case an exception occurred...
312 if (pUnoExc)
313 {
314 // destruct temporary in/inout params
315 for ( ; nTempIndices--; )
316 {
317 sal_Int32 nIndex = pTempIndices[nTempIndices];
318
319 if (pParams[nIndex].bIn) // is in/inout => was constructed
320 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndices], 0 );
321 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
322 }
323 if (pReturnTypeDescr)
324 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
325
327 // has to destruct the any
328 // is here for dummy
329 return typelib_TypeClass_VOID;
330 }
331 else // else no exception occurred...
332 {
333 // temporary params
334 for ( ; nTempIndices--; )
335 {
336 sal_Int32 nIndex = pTempIndices[nTempIndices];
337 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
338
339 if (pParams[nIndex].bOut) // inout/out
340 {
341 // convert and assign
342 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
343 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
344 pThis->getBridge()->getUno2Cpp() );
345 }
346 // destroy temp uno param
347 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
348
349 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
350 }
351 // return
352 if (pCppReturn) // has complex return
353 {
354 if (pUnoReturn != pCppReturn) // needs reconversion
355 {
356 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
357 pThis->getBridge()->getUno2Cpp() );
358 // destroy temp uno return
359 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
360 }
361 // complex return ptr is set to return reg
362 *(void **)pRegisterReturn = pCppReturn;
363 }
364 if (pReturnTypeDescr)
365 {
366 typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
367 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
368 return eRet;
369 }
370 else
371 return typelib_TypeClass_VOID;
372 }
373 }
374
375
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 */ )
381 {
382 static_assert(sizeof(sal_Int32)==sizeof(void *), "### unexpected!");
383
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
388
389 // gpreg: [ret *], this, [other gpr params]
390 // fpreg: [fpr params]
391 // ovrflw: [gpr or fpr params (properly aligned)]
392
393 void * pThis;
394 if (nFunctionIndex & 0x80000000 )
395 {
396 nFunctionIndex &= 0x7fffffff;
397 pThis = gpreg[1];
398 }
399 else
400 {
401 pThis = gpreg[0];
402 }
403#ifdef BRDEBUG
404 fprintf(stderr,"cpp_mediate12,pThis=%p, nFunctionIndex=%d,nVtableOffset=%d\n",pThis,nFunctionIndex,nVtableOffset);
405#endif
406
407 pThis = static_cast< char * >(pThis) - nVtableOffset;
410 pThis);
411#ifdef BRDEBUG
412 fprintf(stderr,"cpp_mediate13,pCppI=%p\n",pCppI);
413#endif
414
415 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
416
417#ifdef BRDEBUG
418 fprintf(stderr,"cpp_mediate2\n");
419#endif
420 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
421 {
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);
432 }
433
434 // determine called method
435 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
436 assert(nMemberPos < pTypeDescr->nAllMembers);
437
438 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
439
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)
447 {
448 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
449 {
450#ifdef BRDEBUG
451 fprintf(stderr,"cpp_mediate4\n");
452#endif
453 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
454 {
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 );
461 }
462 else
463 {
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;
470
471 eRet = cpp2uno_call(
472 pCppI, aMemberDescr.get(),
473 0, // indicates void return
474 1, &aParam,
475 gpreg, fpreg, ovrflw, pRegisterReturn );
476 }
477 break;
478 }
479 case typelib_TypeClass_INTERFACE_METHOD:
480 {
481#ifdef BRDEBUG
482 fprintf(stderr,"cpp_mediate5\n");
483#endif
484 // is METHOD
485 switch (nFunctionIndex)
486 {
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
502 {
503 typelib_TypeDescription * pTD = 0;
504 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() );
505 if (pTD)
506 {
507 XInterface * pInterface = 0;
508 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
509 pCppI->getBridge()->getCppEnv(),
510 (void **)&pInterface, pCppI->getOid().pData,
511 (typelib_InterfaceTypeDescription *)pTD );
512
513 if (pInterface)
514 {
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;
523 }
524 TYPELIB_DANGER_RELEASE( pTD );
525 }
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 );
534 }
535 break;
536 }
537 default:
538 {
539#ifdef BRDEBUG
540 fprintf(stderr,"cpp_mediate6\n");
541#endif
542 throw RuntimeException( "no member description found!", (XInterface *)pThis );
543 }
544 }
545
546 return eRet;
547 }
548
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()
556 {
557 int nFunctionIndex;
558 int vTableOffset;
559 void** pCallStack;
560 void** ovrflw;
561
562 sal_Int32 gpreg[4];
563 double fpreg[2];
564
565 //memcpy( fpreg, fpregptr, 16);
566
567 volatile long nRegReturn[2];
568
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) );
574
575 memcpy( gpreg, pCallStack, 16);
576
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
582
583 //sal_Bool bComplex = nFunctionIndex & 0x80000000 ? sal_True : sal_False;
584
585 typelib_TypeClass aType =
586 cpp_mediate( nFunctionIndex, vTableOffset, (void**)gpreg, (void**)fpreg, ovrflw, (sal_Int64*)nRegReturn );
587
588 switch( aType )
589 {
590
591 // move return value into register space
592 // (will be loaded by machine code snippet)
593
594 case typelib_TypeClass_BOOLEAN:
595 case typelib_TypeClass_BYTE:
596 __asm__( "lbu $2,%0\n\t" : :
597 "m"(nRegReturn[0]) );
598 break;
599
600 case typelib_TypeClass_CHAR:
601 case typelib_TypeClass_UNSIGNED_SHORT:
602 __asm__( "lhu $2,%0\n\t" : :
603 "m"(nRegReturn[0]) );
604 break;
605
606 case typelib_TypeClass_SHORT:
607 __asm__( "lh $2,%0\n\t" : :
608 "m"(nRegReturn[0]) );
609 break;
610
611
612 case typelib_TypeClass_FLOAT:
613 __asm__( "lwc1 $f0,%0\n\t" : :
614 "m" (*((float*)nRegReturn)) );
615 break;
616
617 case typelib_TypeClass_DOUBLE:
618 { register double dret asm("$f0");
619 dret = (*((double*)nRegReturn));
620 (void) dret;
621 }
622 break;
623
624 case typelib_TypeClass_HYPER:
625 case typelib_TypeClass_UNSIGNED_HYPER:
626 __asm__( "lw $3,%0\n\t" : :
627 "m"(nRegReturn[1]) ); // fall through
628
629 default:
630 __asm__( "lw $2,%0\n\t" : :
631 "m"(nRegReturn[0]) );
632 break;
633 }
634 }
635
636
637 int const codeSnippetSize = 56;
638
639 unsigned char * codeSnippet( unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
640 bool simpleRetType)
641 {
642
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
648
649 if (! simpleRetType )
650 functionIndex |= 0x80000000;
651
652 unsigned long * p = (unsigned long *) code;
653
654 // static_assert( sizeof (long) == 4 );
655 assert((((unsigned long)code) & 0x3) == 0 ); //aligned to 4 otherwise a mistake
656
657 /* generate this code */
658 /*
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
681
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!
688 */
689
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);
705
706 }
707
708
709}
710
711
712void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const *bptr, unsigned char const *eptr)
713{
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
721}
722
724
727{
728 return static_cast< Slot * >(block) + 2;
729}
730
731
733 sal_Int32 slotCount)
734{
735 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
736}
737
738namespace {
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:
741struct ProxyRtti {};
742}
743
746 void * block, sal_Int32 slotCount, sal_Int32,
747 typelib_InterfaceTypeDescription *)
748{
749 Slot * slots = mapBlockToVtable(block);
750 slots[-2].fn = 0; //null
751 slots[-1].fn = &typeid(ProxyRtti);
752 return slots + slotCount;
753}
754
756 Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff,
757 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
758 sal_Int32 functionCount, sal_Int32 vtableOffset)
759{
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
768
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;
778 code, functionOffset++, vtableOffset,
780 reinterpret_cast<
781 typelib_InterfaceAttributeTypeDescription * >(
782 member)->pAttributeTypeRef));
783
784 // Setter:
785 if (!reinterpret_cast<
786 typelib_InterfaceAttributeTypeDescription * >(
787 member)->bReadOnly)
788 {
789 (s++)->fn = code + writetoexecdiff;
790 code = codeSnippet(code, functionOffset++, vtableOffset, true);
791 }
792 break;
793
794 case typelib_TypeClass_INTERFACE_METHOD:
795 (s++)->fn = code + writetoexecdiff;
797 code, functionOffset++, vtableOffset,
799 reinterpret_cast<
800 typelib_InterfaceMethodTypeDescription * >(
801 member)->pReturnTypeRef));
802 break;
803
804 default:
805 assert(false);
806 break;
807 }
808 TYPELIB_DANGER_RELEASE(member);
809 }
810 return code;
811}
812
813/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
uno_Mapping * getUno2Cpp()
Definition: bridge.hxx:73
uno_ExtEnvironment * getCppEnv()
Definition: bridge.hxx:69
uno_Mapping * getCpp2Uno()
Definition: bridge.hxx:72
A cpp proxy wrapping a uno interface.
static CppInterfaceProxy * castInterfaceToProxy(void *pInterface)
typelib_InterfaceTypeDescription * getTypeDescr()
static Slot * mapBlockToVtable(void *block)
Given a pointer to a block, turn it into a vtable pointer.
static void flushCode(unsigned char const *begin, unsigned char const *end)
Flush all the generated code snippets of a vtable, on platforms that require it.
static unsigned char * addLocalFunctions(Slot **slots, unsigned char *code, sal_PtrDiff writetoexecdiff, typelib_InterfaceTypeDescription const *type, sal_Int32 functionOffset, sal_Int32 functionCount, sal_Int32 vtableOffset)
Fill the vtable slots corresponding to all local (i.e., not inherited) functions of a given interface...
static Slot * initializeBlock(void *block, sal_Int32 slotCount, sal_Int32 vtableNumber, typelib_InterfaceTypeDescription *type)
Initialize a raw vtable block.
static std::size_t getBlockSize(sal_Int32 slotCount)
Calculate the size of a raw vtable block.
void SAL_CALL uno_destructData(void *pValue, typelib_TypeDescription *pTypeDescr, uno_ReleaseFunc release) SAL_THROW_EXTERN_C()
void SAL_CALL uno_copyAndConvertData(void *pDest, void *pSource, typelib_TypeDescription *pTypeDescr, uno_Mapping *mapping) SAL_THROW_EXTERN_C()
void cpp_vtable_call(sal_Int32 func, sal_Int32 offset, void **pStack)
is called on incoming vtable calls (called by asm snippets)
register sal_uInt32 r28 __asm__("%r28")
#define IS_BIG_ENDIAN
const int codeSnippetSize
static unsigned char * codeSnippet(unsigned char *code, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, bool bHasHiddenParam)
static int cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy *pThis, const typelib_TypeDescription *pMemberTypeDescr, typelib_TypeDescriptionReference *pReturnTypeRef, sal_Int32 nParams, typelib_MethodParameter *pParams, void **gpreg, void **fpreg, void **ovrflw, sal_uInt64 *pRegisterReturn)
sal_Int32 nIndex
void * p
sal_uInt16 nPos
#define SAL_WARN(area, stream)
struct _typelib_TypeDescription typelib_TypeDescription
Definition: msvc/except.hxx:53
struct _uno_Any uno_Any
Definition: msvc/except.hxx:32
typelib_TypeClass __cdecl cpp_mediate(void **pCallStack, const sal_Int32 nFunctionIndex, const sal_Int32 nVtableOffset, sal_Int64 *const pRegisterReturn)
void raiseException(uno_Any *pUnoExc, uno_Mapping *pUno2Cpp)
bool isSimpleType(typelib_TypeClass typeClass)
Determines whether a type is a "simple" type (VOID, BOOLEAN, BYTE, SHORT, UNSIGNED SHORT,...
Definition: types.cxx:28
bool relatesToInterfaceType(typelib_TypeDescription const *type)
Determines whether a type relates to an interface type (is itself an interface type,...
Definition: types.cxx:41
Type
int i
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
sal_Unicode code
#define sal_True
#define sal_False
ResultType type