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