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 
24cdf0e10cSrcweir #include "precompiled_bridges.hxx"
25cdf0e10cSrcweir #include "sal/config.h"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <cstddef>
28cdf0e10cSrcweir #include <cstdlib>
29cdf0e10cSrcweir #include <cstring>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include "bridges/cpp_uno/shared/bridge.hxx"
32cdf0e10cSrcweir #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
33cdf0e10cSrcweir #include "bridges/cpp_uno/shared/types.hxx"
34cdf0e10cSrcweir #include "bridges/cpp_uno/shared/vtablefactory.hxx"
35cdf0e10cSrcweir #include "com/sun/star/uno/genfunc.hxx"
36cdf0e10cSrcweir #include "osl/diagnose.h"
37cdf0e10cSrcweir #include "sal/alloca.h"
38cdf0e10cSrcweir #include "sal/types.h"
39cdf0e10cSrcweir #include "typelib/typeclass.h"
40cdf0e10cSrcweir #include "typelib/typedescription.h"
41cdf0e10cSrcweir #include "typelib/typedescription.hxx"
42cdf0e10cSrcweir #include "uno/any2.h"
43cdf0e10cSrcweir #include "uno/data.h"
44cdf0e10cSrcweir 
45cdf0e10cSrcweir #include "exceptions.hxx"
46cdf0e10cSrcweir #include "flushcode.hxx"
47cdf0e10cSrcweir #include "fp.hxx"
48cdf0e10cSrcweir #include "isdirectreturntype.hxx"
49cdf0e10cSrcweir #include "vtableslotcall.hxx"
50cdf0e10cSrcweir 
51cdf0e10cSrcweir namespace {
52cdf0e10cSrcweir 
53cdf0e10cSrcweir namespace css = com::sun::star;
54cdf0e10cSrcweir 
loadFpRegsFromStruct(typelib_TypeDescription * type,void * data)55cdf0e10cSrcweir void loadFpRegsFromStruct(typelib_TypeDescription * type, void * data) {
56cdf0e10cSrcweir     for (typelib_CompoundTypeDescription * t =
57cdf0e10cSrcweir              reinterpret_cast< typelib_CompoundTypeDescription * >(type);
58cdf0e10cSrcweir          t != NULL; t = t->pBaseTypeDescription)
59cdf0e10cSrcweir     {
60cdf0e10cSrcweir         for (sal_Int32 i = 0; i < t->nMembers; ++i) {
61cdf0e10cSrcweir             switch (t->ppTypeRefs[i]->eTypeClass) {
62cdf0e10cSrcweir             case typelib_TypeClass_FLOAT:
63cdf0e10cSrcweir                 switch (t->pMemberOffsets[i]) {
64cdf0e10cSrcweir                 case 0:
65cdf0e10cSrcweir                     fp_loadf0(reinterpret_cast< float * >(data));
66cdf0e10cSrcweir                     break;
67cdf0e10cSrcweir                 case 4:
68cdf0e10cSrcweir                     fp_loadf1(reinterpret_cast< float * >(data) + 1);
69cdf0e10cSrcweir                     break;
70cdf0e10cSrcweir                 case 8:
71cdf0e10cSrcweir                     fp_loadf2(reinterpret_cast< float * >(data) + 2);
72cdf0e10cSrcweir                     break;
73cdf0e10cSrcweir                 case 12:
74cdf0e10cSrcweir                     fp_loadf3(reinterpret_cast< float * >(data) + 3);
75cdf0e10cSrcweir                     break;
76cdf0e10cSrcweir                 case 16:
77cdf0e10cSrcweir                     fp_loadf4(reinterpret_cast< float * >(data) + 4);
78cdf0e10cSrcweir                     break;
79cdf0e10cSrcweir                 case 20:
80cdf0e10cSrcweir                     fp_loadf5(reinterpret_cast< float * >(data) + 5);
81cdf0e10cSrcweir                     break;
82cdf0e10cSrcweir                 case 24:
83cdf0e10cSrcweir                     fp_loadf6(reinterpret_cast< float * >(data) + 6);
84cdf0e10cSrcweir                     break;
85cdf0e10cSrcweir                 case 28:
86cdf0e10cSrcweir                     fp_loadf7(reinterpret_cast< float * >(data) + 7);
87cdf0e10cSrcweir                     break;
88cdf0e10cSrcweir                 default:
89cdf0e10cSrcweir                     OSL_ASSERT(false);
90cdf0e10cSrcweir                     break;
91cdf0e10cSrcweir                 }
92cdf0e10cSrcweir                 break;
93cdf0e10cSrcweir             case typelib_TypeClass_DOUBLE:
94cdf0e10cSrcweir                 switch (t->pMemberOffsets[i]) {
95cdf0e10cSrcweir                 case 0:
96cdf0e10cSrcweir                     fp_loadd0(reinterpret_cast< double * >(data));
97cdf0e10cSrcweir                     break;
98cdf0e10cSrcweir                 case 8:
99cdf0e10cSrcweir                     fp_loadd2(reinterpret_cast< double * >(data) + 1);
100cdf0e10cSrcweir                     break;
101cdf0e10cSrcweir                 case 16:
102cdf0e10cSrcweir                     fp_loadd4(reinterpret_cast< double * >(data) + 2);
103cdf0e10cSrcweir                     break;
104cdf0e10cSrcweir                 case 24:
105cdf0e10cSrcweir                     fp_loadd6(reinterpret_cast< double * >(data) + 3);
106cdf0e10cSrcweir                     break;
107cdf0e10cSrcweir                 default:
108cdf0e10cSrcweir                     OSL_ASSERT(false);
109cdf0e10cSrcweir                     break;
110cdf0e10cSrcweir                 }
111cdf0e10cSrcweir                 break;
112cdf0e10cSrcweir             case typelib_TypeClass_STRUCT:
113cdf0e10cSrcweir                 {
114cdf0e10cSrcweir                     typelib_TypeDescription * td = NULL;
115cdf0e10cSrcweir                     TYPELIB_DANGER_GET(&td, t->ppTypeRefs[i]);
116cdf0e10cSrcweir                     loadFpRegsFromStruct(td, data);
117cdf0e10cSrcweir                     TYPELIB_DANGER_RELEASE(td);
118cdf0e10cSrcweir                     break;
119cdf0e10cSrcweir                 }
120cdf0e10cSrcweir             }
121cdf0e10cSrcweir         }
122cdf0e10cSrcweir     }
123cdf0e10cSrcweir }
124cdf0e10cSrcweir 
call(bridges::cpp_uno::shared::CppInterfaceProxy * proxy,css::uno::TypeDescription const & description,bool directReturn,typelib_TypeDescriptionReference * returnType,sal_Int32 count,typelib_MethodParameter * parameters,unsigned long * callStack)125cdf0e10cSrcweir void call(
126cdf0e10cSrcweir     bridges::cpp_uno::shared::CppInterfaceProxy * proxy,
127cdf0e10cSrcweir     css::uno::TypeDescription const & description,
128cdf0e10cSrcweir     bool directReturn, typelib_TypeDescriptionReference * returnType,
129cdf0e10cSrcweir     sal_Int32 count, typelib_MethodParameter * parameters,
130cdf0e10cSrcweir     unsigned long * callStack)
131cdf0e10cSrcweir {
132cdf0e10cSrcweir     typelib_TypeDescription * rtd = NULL;
133cdf0e10cSrcweir     if (returnType != NULL) {
134cdf0e10cSrcweir         TYPELIB_DANGER_GET(&rtd, returnType);
135cdf0e10cSrcweir     }
136cdf0e10cSrcweir     bool retconv =
137cdf0e10cSrcweir         rtd != NULL && bridges::cpp_uno::shared::relatesToInterfaceType(rtd);
138cdf0e10cSrcweir     OSL_ASSERT(!(directReturn && retconv));
139cdf0e10cSrcweir     void * retin;
140cdf0e10cSrcweir     void * retout;
141cdf0e10cSrcweir     char retbuf[32];
142cdf0e10cSrcweir     if (directReturn) {
143cdf0e10cSrcweir         retin = returnType == NULL ? NULL : retbuf;
144cdf0e10cSrcweir     } else {
145cdf0e10cSrcweir         retout = reinterpret_cast< void * >(callStack[0]);
146cdf0e10cSrcweir         retin = retconv ? alloca(rtd->nSize) : retout;
147cdf0e10cSrcweir     }
148cdf0e10cSrcweir     void ** args = static_cast< void ** >(alloca(count * sizeof (void *)));
149cdf0e10cSrcweir     void ** cppArgs = static_cast< void ** >(alloca(count * sizeof (void *)));
150cdf0e10cSrcweir     typelib_TypeDescription ** argtds =
151cdf0e10cSrcweir         static_cast< typelib_TypeDescription ** >(
152cdf0e10cSrcweir             alloca(count * sizeof (typelib_TypeDescription *)));
153cdf0e10cSrcweir     union fp { float f; double d; };
154cdf0e10cSrcweir     fp copies[15];
155cdf0e10cSrcweir     sal_Int32 stackPos = directReturn ? 1 : 2; // skip return ptr and this ptr
156cdf0e10cSrcweir     for (sal_Int32 i = 0; i < count; ++i) {
157cdf0e10cSrcweir         typelib_TypeDescription * ptd = NULL;
158cdf0e10cSrcweir         TYPELIB_DANGER_GET(&ptd, parameters[i].pTypeRef);
159cdf0e10cSrcweir         if (!parameters[i].bOut && bridges::cpp_uno::shared::isSimpleType(ptd))
160cdf0e10cSrcweir         {
161cdf0e10cSrcweir             switch (ptd->eTypeClass) {
162cdf0e10cSrcweir             case typelib_TypeClass_FLOAT:
163cdf0e10cSrcweir                 if (stackPos <= 15) {
164cdf0e10cSrcweir                     switch (stackPos) {
165cdf0e10cSrcweir                     case 1:
166cdf0e10cSrcweir                         fp_storef3(&copies[0].f);
167cdf0e10cSrcweir                         break;
168cdf0e10cSrcweir                     case 2:
169cdf0e10cSrcweir                         fp_storef5(&copies[1].f);
170cdf0e10cSrcweir                         break;
171cdf0e10cSrcweir                     case 3:
172cdf0e10cSrcweir                         fp_storef7(&copies[2].f);
173cdf0e10cSrcweir                         break;
174cdf0e10cSrcweir                     case 4:
175cdf0e10cSrcweir                         fp_storef9(&copies[3].f);
176cdf0e10cSrcweir                         break;
177cdf0e10cSrcweir                     case 5:
178cdf0e10cSrcweir                         fp_storef11(&copies[4].f);
179cdf0e10cSrcweir                         break;
180cdf0e10cSrcweir                     case 6:
181cdf0e10cSrcweir                         fp_storef13(&copies[5].f);
182cdf0e10cSrcweir                         break;
183cdf0e10cSrcweir                     case 7:
184cdf0e10cSrcweir                         fp_storef15(&copies[6].f);
185cdf0e10cSrcweir                         break;
186cdf0e10cSrcweir                     case 8:
187cdf0e10cSrcweir                         fp_storef17(&copies[7].f);
188cdf0e10cSrcweir                         break;
189cdf0e10cSrcweir                     case 9:
190cdf0e10cSrcweir                         fp_storef19(&copies[8].f);
191cdf0e10cSrcweir                         break;
192cdf0e10cSrcweir                     case 10:
193cdf0e10cSrcweir                         fp_storef21(&copies[9].f);
194cdf0e10cSrcweir                         break;
195cdf0e10cSrcweir                     case 11:
196cdf0e10cSrcweir                         fp_storef23(&copies[10].f);
197cdf0e10cSrcweir                         break;
198cdf0e10cSrcweir                     case 12:
199cdf0e10cSrcweir                         fp_storef25(&copies[11].f);
200cdf0e10cSrcweir                         break;
201cdf0e10cSrcweir                     case 13:
202cdf0e10cSrcweir                         fp_storef27(&copies[12].f);
203cdf0e10cSrcweir                         break;
204cdf0e10cSrcweir                     case 14:
205cdf0e10cSrcweir                         fp_storef29(&copies[13].f);
206cdf0e10cSrcweir                         break;
207cdf0e10cSrcweir                     case 15:
208cdf0e10cSrcweir                         fp_storef31(&copies[14].f);
209cdf0e10cSrcweir                         break;
210cdf0e10cSrcweir                     default:
211cdf0e10cSrcweir                         OSL_ASSERT(false);
212cdf0e10cSrcweir                         break;
213cdf0e10cSrcweir                     }
214cdf0e10cSrcweir                     args[i] = &copies[stackPos - 1].f;
215cdf0e10cSrcweir                 } else {
216cdf0e10cSrcweir                     args[i] = reinterpret_cast< char * >(callStack + stackPos) +
217cdf0e10cSrcweir                         (sizeof (unsigned long) - sizeof (float));
218cdf0e10cSrcweir                 }
219cdf0e10cSrcweir                 break;
220cdf0e10cSrcweir             case typelib_TypeClass_DOUBLE:
221cdf0e10cSrcweir                 if (stackPos <= 15) {
222cdf0e10cSrcweir                     switch (stackPos) {
223cdf0e10cSrcweir                     case 1:
224cdf0e10cSrcweir                         fp_stored2(&copies[0].d);
225cdf0e10cSrcweir                         break;
226cdf0e10cSrcweir                     case 2:
227cdf0e10cSrcweir                         fp_stored4(&copies[1].d);
228cdf0e10cSrcweir                         break;
229cdf0e10cSrcweir                     case 3:
230cdf0e10cSrcweir                         fp_stored6(&copies[2].d);
231cdf0e10cSrcweir                         break;
232cdf0e10cSrcweir                     case 4:
233cdf0e10cSrcweir                         fp_stored8(&copies[3].d);
234cdf0e10cSrcweir                         break;
235cdf0e10cSrcweir                     case 5:
236cdf0e10cSrcweir                         fp_stored10(&copies[4].d);
237cdf0e10cSrcweir                         break;
238cdf0e10cSrcweir                     case 6:
239cdf0e10cSrcweir                         fp_stored12(&copies[5].d);
240cdf0e10cSrcweir                         break;
241cdf0e10cSrcweir                     case 7:
242cdf0e10cSrcweir                         fp_stored14(&copies[6].d);
243cdf0e10cSrcweir                         break;
244cdf0e10cSrcweir                     case 8:
245cdf0e10cSrcweir                         fp_stored16(&copies[7].d);
246cdf0e10cSrcweir                         break;
247cdf0e10cSrcweir                     case 9:
248cdf0e10cSrcweir                         fp_stored18(&copies[8].d);
249cdf0e10cSrcweir                         break;
250cdf0e10cSrcweir                     case 10:
251cdf0e10cSrcweir                         fp_stored20(&copies[9].d);
252cdf0e10cSrcweir                         break;
253cdf0e10cSrcweir                     case 11:
254cdf0e10cSrcweir                         fp_stored22(&copies[10].d);
255cdf0e10cSrcweir                         break;
256cdf0e10cSrcweir                     case 12:
257cdf0e10cSrcweir                         fp_stored24(&copies[11].d);
258cdf0e10cSrcweir                         break;
259cdf0e10cSrcweir                     case 13:
260cdf0e10cSrcweir                         fp_stored26(&copies[12].d);
261cdf0e10cSrcweir                         break;
262cdf0e10cSrcweir                     case 14:
263cdf0e10cSrcweir                         fp_stored28(&copies[13].d);
264cdf0e10cSrcweir                         break;
265cdf0e10cSrcweir                     case 15:
266cdf0e10cSrcweir                         fp_stored30(&copies[14].d);
267cdf0e10cSrcweir                         break;
268cdf0e10cSrcweir                     default:
269cdf0e10cSrcweir                         OSL_ASSERT(false);
270cdf0e10cSrcweir                         break;
271cdf0e10cSrcweir                     }
272cdf0e10cSrcweir                     args[i] = &copies[stackPos - 1].d;
273cdf0e10cSrcweir                 } else {
274cdf0e10cSrcweir                     args[i] = reinterpret_cast< char * >(callStack + stackPos) +
275cdf0e10cSrcweir                         (sizeof (unsigned long) - sizeof (double));
276cdf0e10cSrcweir                 }
277cdf0e10cSrcweir                 break;
278cdf0e10cSrcweir             default:
279cdf0e10cSrcweir                 OSL_ASSERT(ptd->nSize <= 8);
280cdf0e10cSrcweir                 args[i] = reinterpret_cast< char * >(callStack + stackPos) +
281cdf0e10cSrcweir                     (sizeof (unsigned long) - ptd->nSize);
282cdf0e10cSrcweir                 break;
283cdf0e10cSrcweir             }
284cdf0e10cSrcweir             argtds[i] = NULL;
285cdf0e10cSrcweir             TYPELIB_DANGER_RELEASE(ptd);
286cdf0e10cSrcweir         } else {
287cdf0e10cSrcweir             cppArgs[i] = reinterpret_cast< void * >(callStack[stackPos]);
288cdf0e10cSrcweir             if (!parameters[i].bIn) {
289cdf0e10cSrcweir                 args[i] = alloca(ptd->nSize);
290cdf0e10cSrcweir                 argtds[i] = ptd;
291cdf0e10cSrcweir             } else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd)) {
292cdf0e10cSrcweir                 args[i] = alloca(ptd->nSize);
293cdf0e10cSrcweir                 uno_copyAndConvertData(
294cdf0e10cSrcweir                     args[i], reinterpret_cast< void * >(callStack[stackPos]),
295cdf0e10cSrcweir                     ptd, proxy->getBridge()->getCpp2Uno());
296cdf0e10cSrcweir                 argtds[i] = ptd;
297cdf0e10cSrcweir             } else {
298cdf0e10cSrcweir                 args[i] = reinterpret_cast< void * >(callStack[stackPos]);
299cdf0e10cSrcweir                 argtds[i] = NULL;
300cdf0e10cSrcweir                 TYPELIB_DANGER_RELEASE(ptd);
301cdf0e10cSrcweir             }
302cdf0e10cSrcweir         }
303cdf0e10cSrcweir         ++stackPos;
304cdf0e10cSrcweir     }
305cdf0e10cSrcweir     uno_Any exc;
306cdf0e10cSrcweir     uno_Any * pexc = &exc;
307cdf0e10cSrcweir     proxy->getUnoI()->pDispatcher(
308cdf0e10cSrcweir         proxy->getUnoI(), description.get(), retin, args, &pexc);
309cdf0e10cSrcweir     if (pexc != NULL) {
310cdf0e10cSrcweir         for (sal_Int32 i = 0; i < count; ++i) {
311cdf0e10cSrcweir             if (argtds[i] != NULL) {
312cdf0e10cSrcweir                 if (parameters[i].bIn) {
313cdf0e10cSrcweir                     uno_destructData(args[i], argtds[i], NULL);
314cdf0e10cSrcweir                 }
315cdf0e10cSrcweir                 TYPELIB_DANGER_RELEASE(argtds[i]);
316cdf0e10cSrcweir             }
317cdf0e10cSrcweir         }
318cdf0e10cSrcweir         if (rtd != NULL) {
319cdf0e10cSrcweir             TYPELIB_DANGER_RELEASE(rtd);
320cdf0e10cSrcweir         }
321cdf0e10cSrcweir         bridges::cpp_uno::cc5_solaris_sparc64::raiseException(
322cdf0e10cSrcweir             &exc, proxy->getBridge()->getUno2Cpp());
323cdf0e10cSrcweir         std::abort(); // just in case
324cdf0e10cSrcweir     }
325cdf0e10cSrcweir     for (sal_Int32 i = 0; i < count; ++i) {
326cdf0e10cSrcweir         if (argtds[i] != NULL) {
327cdf0e10cSrcweir             if (parameters[i].bOut) {
328cdf0e10cSrcweir                 uno_destructData(
329cdf0e10cSrcweir                     cppArgs[i], argtds[i],
330cdf0e10cSrcweir                     reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release));
331cdf0e10cSrcweir                 uno_copyAndConvertData(
332cdf0e10cSrcweir                     cppArgs[i], args[i], argtds[i],
333cdf0e10cSrcweir                     proxy->getBridge()->getUno2Cpp());
334cdf0e10cSrcweir             }
335cdf0e10cSrcweir             uno_destructData(args[i], argtds[i], NULL);
336cdf0e10cSrcweir             TYPELIB_DANGER_RELEASE(argtds[i]);
337cdf0e10cSrcweir         }
338cdf0e10cSrcweir     }
339cdf0e10cSrcweir     if (directReturn) {
340cdf0e10cSrcweir         if (rtd != NULL) {
341cdf0e10cSrcweir             switch (rtd->eTypeClass) {
342cdf0e10cSrcweir             case typelib_TypeClass_VOID:
343cdf0e10cSrcweir                 break;
344cdf0e10cSrcweir             case typelib_TypeClass_BOOLEAN:
345cdf0e10cSrcweir                 callStack[0] = *reinterpret_cast< sal_Bool * >(retbuf);
346cdf0e10cSrcweir                 break;
347cdf0e10cSrcweir             case typelib_TypeClass_BYTE:
348cdf0e10cSrcweir                 callStack[0] = *reinterpret_cast< sal_Int8 * >(retbuf);
349cdf0e10cSrcweir                 break;
350cdf0e10cSrcweir             case typelib_TypeClass_SHORT:
351cdf0e10cSrcweir                 callStack[0] = *reinterpret_cast< sal_Int16 * >(retbuf);
352cdf0e10cSrcweir                 break;
353cdf0e10cSrcweir             case typelib_TypeClass_UNSIGNED_SHORT:
354cdf0e10cSrcweir                 callStack[0] = *reinterpret_cast< sal_uInt16 * >(retbuf);
355cdf0e10cSrcweir                 break;
356cdf0e10cSrcweir             case typelib_TypeClass_LONG:
357cdf0e10cSrcweir             case typelib_TypeClass_ENUM:
358cdf0e10cSrcweir                 callStack[0] = *reinterpret_cast< sal_Int32 * >(retbuf);
359cdf0e10cSrcweir                 break;
360cdf0e10cSrcweir             case typelib_TypeClass_UNSIGNED_LONG:
361cdf0e10cSrcweir                 callStack[0] = *reinterpret_cast< sal_uInt32 * >(retbuf);
362cdf0e10cSrcweir                 break;
363cdf0e10cSrcweir             case typelib_TypeClass_HYPER:
364cdf0e10cSrcweir                 callStack[0] = *reinterpret_cast< sal_Int64 * >(retbuf);
365cdf0e10cSrcweir                 break;
366cdf0e10cSrcweir             case typelib_TypeClass_UNSIGNED_HYPER:
367cdf0e10cSrcweir                 callStack[0] = *reinterpret_cast< sal_uInt64 * >(retbuf);
368cdf0e10cSrcweir                 break;
369cdf0e10cSrcweir             case typelib_TypeClass_FLOAT:
370cdf0e10cSrcweir                 fp_loadf0(reinterpret_cast< float * >(retbuf));
371cdf0e10cSrcweir                 break;
372cdf0e10cSrcweir             case typelib_TypeClass_DOUBLE:
373cdf0e10cSrcweir                 fp_loadd0(reinterpret_cast< double * >(retbuf));
374cdf0e10cSrcweir                 break;
375cdf0e10cSrcweir             case typelib_TypeClass_CHAR:
376cdf0e10cSrcweir                 callStack[0] = *reinterpret_cast< sal_Unicode * >(retbuf);
377cdf0e10cSrcweir                 break;
378cdf0e10cSrcweir             case typelib_TypeClass_STRING:
379cdf0e10cSrcweir             case typelib_TypeClass_TYPE:
380cdf0e10cSrcweir             case typelib_TypeClass_SEQUENCE:
381cdf0e10cSrcweir             case typelib_TypeClass_INTERFACE:
382cdf0e10cSrcweir                 callStack[0] = reinterpret_cast< unsigned long >(
383cdf0e10cSrcweir                     *reinterpret_cast< void ** >(retbuf));
384cdf0e10cSrcweir                 break;
385cdf0e10cSrcweir             case typelib_TypeClass_STRUCT:
386cdf0e10cSrcweir                 loadFpRegsFromStruct(rtd, retbuf);
387cdf0e10cSrcweir                 // fall through
388cdf0e10cSrcweir             case typelib_TypeClass_ANY:
389cdf0e10cSrcweir                 std::memcpy(callStack, retbuf, rtd->nSize);
390cdf0e10cSrcweir                 break;
391cdf0e10cSrcweir             default:
392cdf0e10cSrcweir                 OSL_ASSERT(false);
393cdf0e10cSrcweir                 break;
394cdf0e10cSrcweir             }
395cdf0e10cSrcweir         }
396cdf0e10cSrcweir     } else if (retconv) {
397cdf0e10cSrcweir         uno_copyAndConvertData(
398cdf0e10cSrcweir             retout, retin, rtd, proxy->getBridge()->getUno2Cpp());
399cdf0e10cSrcweir         uno_destructData(retin, rtd, NULL);
400cdf0e10cSrcweir     }
401cdf0e10cSrcweir     if (rtd != NULL) {
402cdf0e10cSrcweir         TYPELIB_DANGER_RELEASE(rtd);
403cdf0e10cSrcweir     }
404cdf0e10cSrcweir }
405cdf0e10cSrcweir 
vtableCall(sal_Int32 functionIndex,sal_Int32 vtableOffset,unsigned long * callStack)406cdf0e10cSrcweir extern "C" void vtableCall(
407cdf0e10cSrcweir     sal_Int32 functionIndex, sal_Int32 vtableOffset, unsigned long * callStack)
408cdf0e10cSrcweir {
409cdf0e10cSrcweir     bool direct = static_cast< sal_uInt32 >((functionIndex) & 0x80000000) == 0;
410cdf0e10cSrcweir     functionIndex = static_cast< sal_uInt32 >(functionIndex) & 0x7FFFFFFF;
411cdf0e10cSrcweir     bridges::cpp_uno::shared::CppInterfaceProxy * proxy
412cdf0e10cSrcweir         = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
413cdf0e10cSrcweir             reinterpret_cast< char * >(callStack[direct ? 0 : 1]) -
414cdf0e10cSrcweir             vtableOffset);
415cdf0e10cSrcweir     typelib_InterfaceTypeDescription * type = proxy->getTypeDescr();
416cdf0e10cSrcweir     OSL_ASSERT(functionIndex < type->nMapFunctionIndexToMemberIndex);
417cdf0e10cSrcweir     sal_Int32 pos = type->pMapFunctionIndexToMemberIndex[functionIndex];
418cdf0e10cSrcweir     css::uno::TypeDescription desc(type->ppAllMembers[pos]);
419cdf0e10cSrcweir     switch (desc.get()->eTypeClass) {
420cdf0e10cSrcweir     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
421cdf0e10cSrcweir         if (type->pMapMemberIndexToFunctionIndex[pos] == functionIndex) {
422cdf0e10cSrcweir             // Getter:
423cdf0e10cSrcweir             call(
424cdf0e10cSrcweir                 proxy, desc, direct,
425cdf0e10cSrcweir                 reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >(
426cdf0e10cSrcweir                     desc.get())->pAttributeTypeRef,
427cdf0e10cSrcweir                 0, NULL, callStack);
428cdf0e10cSrcweir         } else {
429cdf0e10cSrcweir             // Setter:
430cdf0e10cSrcweir             typelib_MethodParameter param = {
431cdf0e10cSrcweir                 NULL,
432cdf0e10cSrcweir                 reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >(
433cdf0e10cSrcweir                     desc.get())->pAttributeTypeRef,
434cdf0e10cSrcweir                 true, false };
435cdf0e10cSrcweir             call(proxy, desc, true, NULL, 1, &param, callStack);
436cdf0e10cSrcweir         }
437cdf0e10cSrcweir         break;
438cdf0e10cSrcweir     case typelib_TypeClass_INTERFACE_METHOD:
439cdf0e10cSrcweir         switch (functionIndex) {
440cdf0e10cSrcweir         case 1:
441cdf0e10cSrcweir             proxy->acquireProxy();
442cdf0e10cSrcweir             break;
443cdf0e10cSrcweir         case 2:
444cdf0e10cSrcweir             proxy->releaseProxy();
445cdf0e10cSrcweir             break;
446cdf0e10cSrcweir         case 0:
447cdf0e10cSrcweir             {
448cdf0e10cSrcweir                 typelib_TypeDescription * td = NULL;
449cdf0e10cSrcweir                 TYPELIB_DANGER_GET(
450cdf0e10cSrcweir                     &td,
451cdf0e10cSrcweir                     reinterpret_cast< css::uno::Type * >(
452cdf0e10cSrcweir                         callStack[2])->getTypeLibType());
453cdf0e10cSrcweir                 if (td != NULL) {
454cdf0e10cSrcweir                     css::uno::XInterface * ifc = NULL;
455cdf0e10cSrcweir                     proxy->getBridge()->getCppEnv()->getRegisteredInterface(
456cdf0e10cSrcweir                         proxy->getBridge()->getCppEnv(),
457cdf0e10cSrcweir                         reinterpret_cast< void ** >(&ifc),
458cdf0e10cSrcweir                         proxy->getOid().pData,
459cdf0e10cSrcweir                         reinterpret_cast< typelib_InterfaceTypeDescription * >(
460cdf0e10cSrcweir                             td));
461cdf0e10cSrcweir                     if (ifc != NULL) {
462cdf0e10cSrcweir                         uno_any_construct(
463cdf0e10cSrcweir                             reinterpret_cast< uno_Any * >(callStack[0]), &ifc,
464cdf0e10cSrcweir                             td,
465cdf0e10cSrcweir                             reinterpret_cast< uno_AcquireFunc >(
466cdf0e10cSrcweir                                 css::uno::cpp_acquire));
467cdf0e10cSrcweir                         ifc->release();
468cdf0e10cSrcweir                         TYPELIB_DANGER_RELEASE(td);
469cdf0e10cSrcweir                         break;
470cdf0e10cSrcweir                     }
471cdf0e10cSrcweir                     TYPELIB_DANGER_RELEASE(td);
472cdf0e10cSrcweir                 }
473cdf0e10cSrcweir             } // fall through
474cdf0e10cSrcweir         default:
475cdf0e10cSrcweir             call(
476cdf0e10cSrcweir                 proxy, desc, direct,
477cdf0e10cSrcweir                 reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(
478cdf0e10cSrcweir                     desc.get())->pReturnTypeRef,
479cdf0e10cSrcweir                 reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(
480cdf0e10cSrcweir                     desc.get())->nParams,
481cdf0e10cSrcweir                 reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(
482cdf0e10cSrcweir                     desc.get())->pParams,
483cdf0e10cSrcweir                 callStack);
484cdf0e10cSrcweir         }
485cdf0e10cSrcweir         break;
486cdf0e10cSrcweir     default:
487cdf0e10cSrcweir         OSL_ASSERT(false);
488cdf0e10cSrcweir         break;
489cdf0e10cSrcweir     }
490cdf0e10cSrcweir }
491cdf0e10cSrcweir 
492cdf0e10cSrcweir int const codeSnippetSize = 10 * 4;
493cdf0e10cSrcweir 
generateCodeSnippet(unsigned char * code,sal_Int32 functionIndex,sal_Int32 vtableOffset,bool directReturn)494cdf0e10cSrcweir unsigned char * generateCodeSnippet(
495cdf0e10cSrcweir     unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
496cdf0e10cSrcweir     bool directReturn)
497cdf0e10cSrcweir {
498cdf0e10cSrcweir     sal_uInt32 index = functionIndex;
499cdf0e10cSrcweir     if (!directReturn) {
500cdf0e10cSrcweir         index |= 0x80000000;
501cdf0e10cSrcweir     }
502cdf0e10cSrcweir     unsigned int * p = reinterpret_cast< unsigned int * >(code);
503cdf0e10cSrcweir     OSL_ASSERT(sizeof (unsigned int) == 4);
504cdf0e10cSrcweir     // 0*4: save %sp, -176, %sp ! minimal stack frame:
505cdf0e10cSrcweir     *p++ = 0x9DE3BF50;
506cdf0e10cSrcweir     // 1*4: rd %pc, %l0:
507cdf0e10cSrcweir     *p++ = 0xA1414000;
508cdf0e10cSrcweir     // 2*4: ldx %l0, (8-1)*4, %l0:
509cdf0e10cSrcweir     *p++ = 0xE05C201C;
510cdf0e10cSrcweir     // 3*4: sethi %hi(index), %o0:
511cdf0e10cSrcweir     *p++ = 0x11000000 | (index >> 10);
512cdf0e10cSrcweir     // 4*4: or %o0, %lo(index), %o0:
513cdf0e10cSrcweir     *p++ = 0x90122000 | (index & 0x3FF);
514cdf0e10cSrcweir     // 5*4: sethi %hi(vtableOffset), %o1:
515cdf0e10cSrcweir     *p++ = 0x13000000 | (vtableOffset >> 10);
516cdf0e10cSrcweir     // 6*4: jmpl %l0, %g0, %g0:
517cdf0e10cSrcweir     *p++ = 0x81C40000;
518cdf0e10cSrcweir     // 7*4: or %o1, %lo(vtableOffset), %o1:
519cdf0e10cSrcweir     *p++ = 0x92126000 | (vtableOffset & 0x3FF);
520cdf0e10cSrcweir     // 8*4: .xword privateSnippetExecutor:
521cdf0e10cSrcweir     *reinterpret_cast< unsigned long * >(p) =
522cdf0e10cSrcweir         reinterpret_cast< unsigned long >(vtableSlotCall);
523cdf0e10cSrcweir     return code + codeSnippetSize;
524cdf0e10cSrcweir }
525cdf0e10cSrcweir 
526cdf0e10cSrcweir }
527cdf0e10cSrcweir 
528cdf0e10cSrcweir struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
529cdf0e10cSrcweir 
530cdf0e10cSrcweir bridges::cpp_uno::shared::VtableFactory::Slot *
mapBlockToVtable(void * block)531cdf0e10cSrcweir bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) {
532cdf0e10cSrcweir     return static_cast< Slot * >(block) + 1;
533cdf0e10cSrcweir }
534cdf0e10cSrcweir 
getBlockSize(sal_Int32 slotCount)535cdf0e10cSrcweir sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
536cdf0e10cSrcweir     sal_Int32 slotCount)
537cdf0e10cSrcweir {
538cdf0e10cSrcweir     return (slotCount + 3) * sizeof (Slot) + slotCount * codeSnippetSize;
539cdf0e10cSrcweir }
540cdf0e10cSrcweir 
541cdf0e10cSrcweir bridges::cpp_uno::shared::VtableFactory::Slot *
initializeBlock(void * block,sal_Int32 slotCount)542cdf0e10cSrcweir bridges::cpp_uno::shared::VtableFactory::initializeBlock(
543cdf0e10cSrcweir     void * block, sal_Int32 slotCount)
544cdf0e10cSrcweir {
545cdf0e10cSrcweir     Slot * slots = mapBlockToVtable(block) + 2;
546cdf0e10cSrcweir     slots[-3].fn = NULL; // RTTI
547cdf0e10cSrcweir     slots[-2].fn = NULL; // null
548cdf0e10cSrcweir     slots[-1].fn = NULL; // destructor
549cdf0e10cSrcweir     return slots + slotCount;
550cdf0e10cSrcweir }
551cdf0e10cSrcweir 
addLocalFunctions(Slot ** slots,unsigned char * code,typelib_InterfaceTypeDescription const * type,sal_Int32 functionOffset,sal_Int32 functionCount,sal_Int32 vtableOffset)552cdf0e10cSrcweir unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
553cdf0e10cSrcweir     Slot ** slots, unsigned char * code,
554cdf0e10cSrcweir     typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
555cdf0e10cSrcweir     sal_Int32 functionCount, sal_Int32 vtableOffset)
556cdf0e10cSrcweir {
557cdf0e10cSrcweir     (*slots) -= functionCount;
558cdf0e10cSrcweir     Slot * s = *slots;
559cdf0e10cSrcweir     for (sal_Int32 i = 0; i < type->nMembers; ++i) {
560cdf0e10cSrcweir         typelib_TypeDescription * member = 0;
561cdf0e10cSrcweir         TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
562cdf0e10cSrcweir         OSL_ASSERT(member != 0);
563cdf0e10cSrcweir         switch (member->eTypeClass) {
564cdf0e10cSrcweir         case typelib_TypeClass_INTERFACE_ATTRIBUTE:
565cdf0e10cSrcweir             // Getter:
566cdf0e10cSrcweir             (s++)->fn = code;
567cdf0e10cSrcweir             code = generateCodeSnippet(
568cdf0e10cSrcweir                 code, functionOffset++, vtableOffset,
569cdf0e10cSrcweir                 bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType(
570cdf0e10cSrcweir                     reinterpret_cast<
571cdf0e10cSrcweir                     typelib_InterfaceAttributeTypeDescription * >(
572cdf0e10cSrcweir                         member)->pAttributeTypeRef));
573cdf0e10cSrcweir             // Setter:
574cdf0e10cSrcweir             if (!reinterpret_cast<
575cdf0e10cSrcweir                 typelib_InterfaceAttributeTypeDescription * >(
576cdf0e10cSrcweir                     member)->bReadOnly)
577cdf0e10cSrcweir             {
578cdf0e10cSrcweir                 (s++)->fn = code;
579cdf0e10cSrcweir                 code = generateCodeSnippet(
580cdf0e10cSrcweir                     code, functionOffset++, vtableOffset, true);
581cdf0e10cSrcweir             }
582cdf0e10cSrcweir             break;
583cdf0e10cSrcweir 
584cdf0e10cSrcweir         case typelib_TypeClass_INTERFACE_METHOD:
585cdf0e10cSrcweir             (s++)->fn = code;
586cdf0e10cSrcweir             code = generateCodeSnippet(
587cdf0e10cSrcweir                 code, functionOffset++, vtableOffset,
588cdf0e10cSrcweir                 bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType(
589cdf0e10cSrcweir                     reinterpret_cast<
590cdf0e10cSrcweir                     typelib_InterfaceMethodTypeDescription * >(
591cdf0e10cSrcweir                         member)->pReturnTypeRef));
592cdf0e10cSrcweir             break;
593cdf0e10cSrcweir 
594cdf0e10cSrcweir         default:
595cdf0e10cSrcweir             OSL_ASSERT(false);
596cdf0e10cSrcweir             break;
597cdf0e10cSrcweir         }
598cdf0e10cSrcweir         TYPELIB_DANGER_RELEASE(member);
599cdf0e10cSrcweir     }
600cdf0e10cSrcweir     return code;
601cdf0e10cSrcweir }
602cdf0e10cSrcweir 
flushCode(unsigned char const * begin,unsigned char const * end)603cdf0e10cSrcweir void bridges::cpp_uno::shared::VtableFactory::flushCode(
604cdf0e10cSrcweir     unsigned char const * begin, unsigned char const * end)
605cdf0e10cSrcweir {
606cdf0e10cSrcweir     bridges::cpp_uno::cc5_solaris_sparc64::flushCode(begin, end);
607cdf0e10cSrcweir }
608