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