LibreOffice Module bridges (master) 1
gcc3_macosx_x86-64/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
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <typeinfo>
24
25#include <rtl/alloc.h>
26#include <sal/log.hxx>
27
28#include <com/sun/star/uno/genfunc.hxx>
29#include <com/sun/star/uno/RuntimeException.hpp>
30#include <uno/data.h>
31#include <typelib/typedescription.hxx>
32
33#include <bridge.hxx>
34#include <cppinterfaceproxy.hxx>
35#include <types.hxx>
36#include <vtablefactory.hxx>
37
38#include "abi.hxx"
39#include "call.hxx"
40#include "share.hxx"
41
42using namespace ::osl;
43using namespace ::com::sun::star::uno;
44
45
46// Perform the UNO call
47//
48// We must convert the parameters stored in gpreg, fpreg and ovrflw to UNO
49// arguments and call pThis->getUnoI()->pDispatcher.
50//
51// gpreg: [ret *], this, [gpr params]
52// fpreg: [fpr params]
53// ovrflw: [gpr or fpr params (properly aligned)]
54//
55// [ret *] is present when we are returning a structure bigger than 16 bytes
56// Simple types are returned in rax, rdx (int), or xmm0, xmm1 (fp).
57// Similarly structures <= 16 bytes are in rax, rdx, xmm0, xmm1 as necessary.
58//
59// The return value is the same as for cpp_vtable_call.
60static int cpp2uno_call(
62 const typelib_TypeDescription * pMemberTypeDescr,
63 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
64 sal_Int32 nParams, typelib_MethodParameter * pParams,
65 void ** gpreg, void ** fpreg, void ** ovrflw,
66 sal_uInt64 * pRegisterReturn /* space for register return */ )
67{
68 unsigned int nr_gpr = 0; //number of gpr registers used
69 unsigned int nr_fpr = 0; //number of fpr registers used
70
71 // return
72 typelib_TypeDescription * pReturnTypeDescr = nullptr;
73 if (pReturnTypeRef)
74 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
75 x86_64::ReturnKind returnKind
76 = (pReturnTypeRef == nullptr || pReturnTypeRef->eTypeClass == typelib_TypeClass_VOID)
78
79 void * pUnoReturn = nullptr;
80 void * pCppReturn = nullptr; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
81
82 if ( pReturnTypeDescr )
83 {
84 if ( returnKind == x86_64::ReturnKind::Memory )
85 {
86 pCppReturn = *gpreg++;
87 nr_gpr++;
88
89 pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
90 ? alloca( pReturnTypeDescr->nSize )
91 : pCppReturn ); // direct way
92 }
93 else
94 pUnoReturn = pRegisterReturn; // direct way for simple types
95 }
96
97 // pop this
98 gpreg++;
99 nr_gpr++;
100
101 // stack space
102 // parameters
103 void ** pUnoArgs = static_cast<void **>(alloca( 4 * sizeof(void *) * nParams ));
104 void ** pCppArgs = pUnoArgs + nParams;
105 // indices of values this have to be converted (interface conversion cpp<=>uno)
106 sal_Int32 * pTempIndices = reinterpret_cast<sal_Int32 *>(pUnoArgs + (2 * nParams));
107 // type descriptions for reconversions
108 typelib_TypeDescription ** ppTempParamTypeDescr = reinterpret_cast<typelib_TypeDescription **>(pUnoArgs + (3 * nParams));
109
110 sal_Int32 nTempIndices = 0;
111
112 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
113 {
114 const typelib_MethodParameter & rParam = pParams[nPos];
115
116 if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( rParam.pTypeRef ) ) // value
117 {
118 int nUsedGPR = 0;
119 int nUsedSSE = 0;
120#ifndef NDEBUG
121 bool bFitsRegisters =
122#endif
123 x86_64::examine_argument( rParam.pTypeRef, nUsedGPR, nUsedSSE );
124
125 // Simple types must fit exactly one register on x86_64
126 assert(bFitsRegisters && ( ( nUsedSSE == 1 && nUsedGPR == 0 ) || ( nUsedSSE == 0 && nUsedGPR == 1 ) ));
127
128 if ( nUsedSSE == 1 )
129 {
130 if ( nr_fpr < x86_64::MAX_SSE_REGS )
131 {
132 pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++;
133 nr_fpr++;
134 }
135 else
136 pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
137 }
138 else if ( nUsedGPR == 1 )
139 {
140 if ( nr_gpr < x86_64::MAX_GPR_REGS )
141 {
142 pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++;
143 nr_gpr++;
144 }
145 else
146 pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
147 }
148 }
149 else // ref
150 {
151 typelib_TypeDescription * pParamTypeDescr = nullptr;
152 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
153
154 void *pCppStack;
155 if ( nr_gpr < x86_64::MAX_GPR_REGS )
156 {
157 pCppArgs[nPos] = pCppStack = *gpreg++;
158 nr_gpr++;
159 }
160 else
161 pCppArgs[nPos] = pCppStack = *ovrflw++;
162
163 if (! rParam.bIn) // is pure out
164 {
165 // uno out is unconstructed mem!
166 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
167 pTempIndices[nTempIndices] = nPos;
168 // will be released at reconversion
169 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
170 }
171 else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ) ) // is in/inout
172 {
173 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
174 pCppStack, pParamTypeDescr,
175 pThis->getBridge()->getCpp2Uno() );
176 pTempIndices[nTempIndices] = nPos; // has to be reconverted
177 // will be released at reconversion
178 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
179 }
180 else // direct way
181 {
182 pUnoArgs[nPos] = pCppStack;
183 // no longer needed
184 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
185 }
186 }
187 }
188
189 // ExceptionHolder
190 uno_Any aUnoExc; // Any will be constructed by callee
191 uno_Any * pUnoExc = &aUnoExc;
192
193 // invoke uno dispatch call
194 (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
195
196 // in case an exception occurred...
197 if ( pUnoExc )
198 {
199 // destruct temporary in/inout params
200 for ( ; nTempIndices--; )
201 {
202 sal_Int32 nIndex = pTempIndices[nTempIndices];
203
204 if (pParams[nIndex].bIn) // is in/inout => was constructed
205 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndices], nullptr );
206 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
207 }
208 if (pReturnTypeDescr)
209 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
210
211 CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
212 // is here for dummy
213 return 0;
214 }
215 else // else no exception occurred...
216 {
217 // temporary params
218 for ( ; nTempIndices--; )
219 {
220 sal_Int32 nIndex = pTempIndices[nTempIndices];
221 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
222
223 if ( pParams[nIndex].bOut ) // inout/out
224 {
225 // convert and assign
226 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
227 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
228 pThis->getBridge()->getUno2Cpp() );
229 }
230 // destroy temp uno param
231 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, nullptr );
232
233 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
234 }
235 // return
236 if ( pCppReturn ) // has complex return
237 {
238 if ( pUnoReturn != pCppReturn ) // needs reconversion
239 {
240 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
241 pThis->getBridge()->getUno2Cpp() );
242 // destroy temp uno return
243 uno_destructData( pUnoReturn, pReturnTypeDescr, nullptr );
244 }
245 // complex return ptr is set to return reg
246 *reinterpret_cast<void **>(pRegisterReturn) = pCppReturn;
247 }
248 if ( pReturnTypeDescr )
249 {
250 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
251 }
252 switch (returnKind) {
254 return 0;
256 return 1;
257 default:
258 return -1;
259 }
260 }
261}
262
263// Returns -1 for the general case where potential return values from privateSnippetExecutor can be
264// copied from pRegisterReturn to both %rax and %rdx (in that order) and to %xmm0 and %xmm1 (in that
265// order)---each specific return type will only require a subset of that copy operations, but the
266// other copies to those non--callee-saved registers will be redundant and harmless. Returns 0 for
267// the special case where return values from privateSnippetExecutor must be copied from
268// pRegisterReturn to %xmm0 and %rax (in that order). Returns 1 for the special case where return
269// privateSnippetExecutor must be copied from pRegisterReturn to %rax and %xmm0 (in that order).
271 sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
272 void ** gpreg, void ** fpreg, void ** ovrflw,
273 sal_uInt64 * pRegisterReturn /* space for register return */ )
274{
275 // gpreg: [ret *], this, [other gpr params]
276 // fpreg: [fpr params]
277 // ovrflw: [gpr or fpr params (properly aligned)]
278 void * pThis;
279 if ( nFunctionIndex & 0x80000000 )
280 {
281 nFunctionIndex &= 0x7fffffff;
282 pThis = gpreg[1];
283 }
284 else
285 {
286 pThis = gpreg[0];
287 }
288 pThis = static_cast<char *>( pThis ) - nVtableOffset;
289
292
293 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
294
295 if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex )
296 {
297 SAL_WARN(
298 "bridges",
299 "illegal " << OUString::unacquired(&pTypeDescr->aBase.pTypeName)
300 << " vtable index " << nFunctionIndex << "/"
301 << pTypeDescr->nMapFunctionIndexToMemberIndex);
302 throw RuntimeException(
303 ("illegal " + OUString::unacquired(&pTypeDescr->aBase.pTypeName)
304 + " vtable index " + OUString::number(nFunctionIndex) + "/"
305 + OUString::number(pTypeDescr->nMapFunctionIndexToMemberIndex)),
306 reinterpret_cast<XInterface *>( pCppI ) );
307 }
308
309 // determine called method
310 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
311 assert(nMemberPos < pTypeDescr->nAllMembers);
312
313 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
314
315 int eRet;
316 switch ( aMemberDescr.get()->eTypeClass )
317 {
318 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
319 {
320 typelib_TypeDescriptionReference *pAttrTypeRef =
321 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef;
322
323 if ( pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
324 {
325 // is GET method
326 eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef,
327 0, nullptr, // no params
328 gpreg, fpreg, ovrflw, pRegisterReturn );
329 }
330 else
331 {
332 // is SET method
333 typelib_MethodParameter aParam;
334 aParam.pTypeRef = pAttrTypeRef;
335 aParam.bIn = true;
336 aParam.bOut = false;
337
338 eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
339 nullptr, // indicates void return
340 1, &aParam,
341 gpreg, fpreg, ovrflw, pRegisterReturn );
342 }
343 break;
344 }
345 case typelib_TypeClass_INTERFACE_METHOD:
346 {
347 // is METHOD
348 switch ( nFunctionIndex )
349 {
350 case 1: // acquire()
351 pCppI->acquireProxy(); // non virtual call!
352 eRet = 0;
353 break;
354 case 2: // release()
355 pCppI->releaseProxy(); // non virtual call!
356 eRet = 0;
357 break;
358 case 0: // queryInterface() opt
359 {
360 typelib_TypeDescription * pTD = nullptr;
361 TYPELIB_DANGER_GET( &pTD, static_cast<Type *>( gpreg[2] )->getTypeLibType() );
362 if ( pTD )
363 {
364 XInterface * pInterface = nullptr;
365 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
366 ( pCppI->getBridge()->getCppEnv(),
367 reinterpret_cast<void **>(&pInterface),
368 pCppI->getOid().pData,
369 reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
370
371 if ( pInterface )
372 {
373 ::uno_any_construct( static_cast<uno_Any *>( gpreg[0] ),
374 &pInterface, pTD, cpp_acquire );
375
376 pInterface->release();
377 TYPELIB_DANGER_RELEASE( pTD );
378
379 reinterpret_cast<void **>( pRegisterReturn )[0] = gpreg[0];
380 eRet = 0;
381 break;
382 }
383 TYPELIB_DANGER_RELEASE( pTD );
384 }
385 [[fallthrough]]; // else perform queryInterface()
386 }
387 default:
388 {
389 typelib_InterfaceMethodTypeDescription *pMethodTD =
390 reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
391
392 eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
393 pMethodTD->pReturnTypeRef,
394 pMethodTD->nParams,
395 pMethodTD->pParams,
396 gpreg, fpreg, ovrflw, pRegisterReturn );
397 }
398 }
399 break;
400 }
401 default:
402 {
403 throw RuntimeException("no member description found!",
404 reinterpret_cast<XInterface *>( pCppI ) );
405 }
406 }
407
408 return eRet;
409}
410
411const int codeSnippetSize = 24;
412
413// Generate a trampoline that redirects method calls to
414// privateSnippetExecutor().
415//
416// privateSnippetExecutor() saves all the registers that are used for
417// parameter passing on x86_64, and calls the cpp_vtable_call().
418// When it returns, privateSnippetExecutor() sets the return value.
419//
420// Note: The code snippet we build here must not create a stack frame,
421// otherwise the UNO exceptions stop working thanks to non-existing
422// unwinding info.
423static unsigned char * codeSnippet( unsigned char * code,
424 sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
425 bool bHasHiddenParam )
426{
427 sal_uInt64 nOffsetAndIndex = ( static_cast<sal_uInt64>(nVtableOffset) << 32 ) | static_cast<sal_uInt64>(nFunctionIndex);
428
429 if ( bHasHiddenParam )
430 nOffsetAndIndex |= 0x80000000;
431
432 // movq $<nOffsetAndIndex>, %r10
433 *reinterpret_cast<sal_uInt16 *>( code ) = 0xba49;
434 *reinterpret_cast<sal_uInt16 *>( code + 2 ) = nOffsetAndIndex & 0xFFFF;
435 *reinterpret_cast<sal_uInt32 *>( code + 4 ) = nOffsetAndIndex >> 16;
436 *reinterpret_cast<sal_uInt16 *>( code + 8 ) = nOffsetAndIndex >> 48;
437
438 // movq $<address of the privateSnippetExecutor>, %r11
439 *reinterpret_cast<sal_uInt16 *>( code + 10 ) = 0xbb49;
440 *reinterpret_cast<sal_uInt32 *>( code + 12 )
441 = reinterpret_cast<sal_uInt64>(privateSnippetExecutor);
442 *reinterpret_cast<sal_uInt32 *>( code + 16 )
443 = reinterpret_cast<sal_uInt64>(privateSnippetExecutor) >> 32;
444
445 // jmpq *%r11
446 *reinterpret_cast<sal_uInt32 *>( code + 20 ) = 0x00e3ff49;
447
448#if OSL_DEBUG_LEVEL > 1
449 fprintf(stderr,
450 "==> codeSnippet, functionIndex=%d%s, vtableOffset=%d\n",
451 nFunctionIndex, (bHasHiddenParam ? "|0x80000000":""), nVtableOffset);
452#endif
453
454 return code + codeSnippetSize;
455}
456
458
461{
462 return static_cast< Slot * >(block) + 2;
463}
464
466 sal_Int32 slotCount)
467{
468 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
469}
470
471namespace {
472// Some dummy type whose RTTI is used in the synthesized proxy vtables to make uses of dynamic_cast
473// on such proxy objects not crash:
474struct ProxyRtti {};
475}
476
479 void * block, sal_Int32 slotCount, sal_Int32,
480 typelib_InterfaceTypeDescription *)
481{
482 Slot * slots = mapBlockToVtable(block);
483 slots[-2].fn = nullptr;
484 slots[-1].fn = &typeid(ProxyRtti);
485 return slots + slotCount;
486}
487
488
490 Slot ** slots, unsigned char * code,
491 typelib_InterfaceTypeDescription const * type, sal_Int32 nFunctionOffset,
492 sal_Int32 functionCount, sal_Int32 nVtableOffset )
493{
494 const sal_PtrDiff writetoexecdiff = 0;
495 (*slots) -= functionCount;
496 Slot * s = *slots;
497 for ( sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos )
498 {
499 typelib_TypeDescription * pTD = nullptr;
500
501 TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] );
502 assert(pTD);
503
504 if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass )
505 {
506 typelib_InterfaceAttributeTypeDescription *pAttrTD =
507 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
508
509 // get method
510 (s++)->fn = code + writetoexecdiff;
511 code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
512 x86_64::return_in_hidden_param( pAttrTD->pAttributeTypeRef ) );
513
514 if ( ! pAttrTD->bReadOnly )
515 {
516 // set method
517 (s++)->fn = code + writetoexecdiff;
518 code = codeSnippet( code, nFunctionOffset++, nVtableOffset, false );
519 }
520 }
521 else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass )
522 {
523 typelib_InterfaceMethodTypeDescription *pMethodTD =
524 reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
525
526 (s++)->fn = code + writetoexecdiff;
527 code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
528 x86_64::return_in_hidden_param( pMethodTD->pReturnTypeRef ) );
529 }
530 else
531 assert(false);
532
533 TYPELIB_DANGER_RELEASE( pTD );
534 }
535 return code;
536}
537
539 SAL_UNUSED_PARAMETER unsigned char const *,
540 SAL_UNUSED_PARAMETER unsigned char const * )
541{}
542
543/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
uno_Mapping * getUno2Cpp()
Definition: bridge.hxx:73
uno_ExtEnvironment * getCppEnv()
Definition: bridge.hxx:69
uno_Mapping * getCpp2Uno()
Definition: bridge.hxx:72
A cpp proxy wrapping a uno interface.
static CppInterfaceProxy * castInterfaceToProxy(void *pInterface)
typelib_InterfaceTypeDescription * getTypeDescr()
static Slot * mapBlockToVtable(void *block)
Given a pointer to a block, turn it into a vtable pointer.
static void flushCode(unsigned char const *begin, unsigned char const *end)
Flush all the generated code snippets of a vtable, on platforms that require it.
static unsigned char * addLocalFunctions(Slot **slots, unsigned char *code, sal_PtrDiff writetoexecdiff, typelib_InterfaceTypeDescription const *type, sal_Int32 functionOffset, sal_Int32 functionCount, sal_Int32 vtableOffset)
Fill the vtable slots corresponding to all local (i.e., not inherited) functions of a given interface...
static Slot * initializeBlock(void *block, sal_Int32 slotCount, sal_Int32 vtableNumber, typelib_InterfaceTypeDescription *type)
Initialize a raw vtable block.
static std::size_t getBlockSize(sal_Int32 slotCount)
Calculate the size of a raw vtable block.
void SAL_CALL uno_destructData(void *pValue, typelib_TypeDescription *pTypeDescr, uno_ReleaseFunc release) SAL_THROW_EXTERN_C()
void SAL_CALL uno_copyAndConvertData(void *pDest, void *pSource, typelib_TypeDescription *pTypeDescr, uno_Mapping *mapping) SAL_THROW_EXTERN_C()
void(* privateSnippetExecutor)()
const int codeSnippetSize
int cpp_vtable_call(sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, void **gpreg, void **fpreg, void **ovrflw, sal_uInt64 *pRegisterReturn)
static unsigned char * codeSnippet(unsigned char *code, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, bool bHasHiddenParam)
static int cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy *pThis, const typelib_TypeDescription *pMemberTypeDescr, typelib_TypeDescriptionReference *pReturnTypeRef, sal_Int32 nParams, typelib_MethodParameter *pParams, void **gpreg, void **fpreg, void **ovrflw, sal_uInt64 *pRegisterReturn)
sal_Int32 nIndex
sal_uInt16 nPos
#define SAL_WARN(area, stream)
struct _typelib_TypeDescription typelib_TypeDescription
Definition: msvc/except.hxx:53
struct _uno_Any uno_Any
Definition: msvc/except.hxx:32
void raiseException(uno_Any *pUnoExc, uno_Mapping *pUno2Cpp)
bool isSimpleType(typelib_TypeClass typeClass)
Determines whether a type is a "simple" type (VOID, BOOLEAN, BYTE, SHORT, UNSIGNED SHORT,...
Definition: types.cxx:28
bool relatesToInterfaceType(typelib_TypeDescription const *type)
Determines whether a type relates to an interface type (is itself an interface type,...
Definition: types.cxx:41
Type
bool examine_argument(typelib_TypeDescriptionReference *pTypeRef, int &nUsedGPR, int &nUsedSSE) noexcept
bool return_in_hidden_param(typelib_TypeDescriptionReference *pTypeRef) noexcept
Does function that returns this type use a hidden parameter, or registers?
const sal_uInt32 MAX_SSE_REGS
ReturnKind getReturnKind(typelib_TypeDescriptionReference *type) noexcept
const sal_uInt32 MAX_GPR_REGS
sal_Unicode code
ResultType type