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