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