1b146d3b3SDamjan Jovanovic /**************************************************************
2b146d3b3SDamjan Jovanovic *
3b146d3b3SDamjan Jovanovic * Licensed to the Apache Software Foundation (ASF) under one
4b146d3b3SDamjan Jovanovic * or more contributor license agreements. See the NOTICE file
5b146d3b3SDamjan Jovanovic * distributed with this work for additional information
6b146d3b3SDamjan Jovanovic * regarding copyright ownership. The ASF licenses this file
7b146d3b3SDamjan Jovanovic * to you under the Apache License, Version 2.0 (the
8b146d3b3SDamjan Jovanovic * "License"); you may not use this file except in compliance
9b146d3b3SDamjan Jovanovic * with the License. You may obtain a copy of the License at
10b146d3b3SDamjan Jovanovic *
11b146d3b3SDamjan Jovanovic * http://www.apache.org/licenses/LICENSE-2.0
12b146d3b3SDamjan Jovanovic *
13b146d3b3SDamjan Jovanovic * Unless required by applicable law or agreed to in writing,
14b146d3b3SDamjan Jovanovic * software distributed under the License is distributed on an
15b146d3b3SDamjan Jovanovic * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16b146d3b3SDamjan Jovanovic * KIND, either express or implied. See the License for the
17b146d3b3SDamjan Jovanovic * specific language governing permissions and limitations
18b146d3b3SDamjan Jovanovic * under the License.
19b146d3b3SDamjan Jovanovic *
20b146d3b3SDamjan Jovanovic *************************************************************/
21b146d3b3SDamjan Jovanovic
22b146d3b3SDamjan Jovanovic
23b146d3b3SDamjan Jovanovic
24b146d3b3SDamjan Jovanovic // MARKER(update_precomp.py): autogen include statement, do not remove
25b146d3b3SDamjan Jovanovic #include "precompiled_bridges.hxx"
26b146d3b3SDamjan Jovanovic
27b146d3b3SDamjan Jovanovic #include <malloc.h>
28b146d3b3SDamjan Jovanovic
29b146d3b3SDamjan Jovanovic #include <com/sun/star/uno/genfunc.hxx>
30b146d3b3SDamjan Jovanovic #include <uno/data.h>
31b146d3b3SDamjan Jovanovic #include <typelib/typedescription.hxx>
32b146d3b3SDamjan Jovanovic
33b146d3b3SDamjan Jovanovic #include "bridges/cpp_uno/shared/bridge.hxx"
34b146d3b3SDamjan Jovanovic #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
35b146d3b3SDamjan Jovanovic #include "bridges/cpp_uno/shared/types.hxx"
36b146d3b3SDamjan Jovanovic #include "bridges/cpp_uno/shared/vtablefactory.hxx"
37b146d3b3SDamjan Jovanovic
38b146d3b3SDamjan Jovanovic #include "abi.hxx"
39b146d3b3SDamjan Jovanovic #include "mscx.hxx"
40b146d3b3SDamjan Jovanovic
41b146d3b3SDamjan Jovanovic using namespace ::rtl;
42b146d3b3SDamjan Jovanovic using namespace ::com::sun::star::uno;
43b146d3b3SDamjan Jovanovic
44b146d3b3SDamjan Jovanovic namespace
45b146d3b3SDamjan Jovanovic {
46b146d3b3SDamjan Jovanovic
47b146d3b3SDamjan Jovanovic //==================================================================================================
48b146d3b3SDamjan Jovanovic
49b146d3b3SDamjan Jovanovic // Perform the UNO call
50b146d3b3SDamjan Jovanovic //
51*e405e85bSDamjan Jovanovic // We must convert the parameters stored in pCallStack to UNO
52b146d3b3SDamjan Jovanovic // arguments and call pThis->getUnoI()->pDispatcher.
53b146d3b3SDamjan Jovanovic //
54b146d3b3SDamjan Jovanovic // pCallStack: ret addr, this, [ret *], [params]
55b146d3b3SDamjan Jovanovic //
56b146d3b3SDamjan Jovanovic // [ret *] is present when we are returning a structure bigger than 8 bytes
57b146d3b3SDamjan Jovanovic // Simple types are returned in rax, or xmm0 (fp).
58b146d3b3SDamjan Jovanovic // Similarly structures <= 8 bytes are in rax, xmm0 as necessary.
cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy * pThis,const typelib_TypeDescription * pMemberTypeDescr,typelib_TypeDescriptionReference * pReturnTypeRef,sal_Int32 nParams,typelib_MethodParameter * pParams,void ** pCallStack,sal_uInt64 * pRegisterReturn)59b146d3b3SDamjan Jovanovic static inline typelib_TypeClass cpp2uno_call(
60b146d3b3SDamjan Jovanovic bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
61b146d3b3SDamjan Jovanovic const typelib_TypeDescription * pMemberTypeDescr,
62b146d3b3SDamjan Jovanovic typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
63b146d3b3SDamjan Jovanovic sal_Int32 nParams, typelib_MethodParameter * pParams,
64b146d3b3SDamjan Jovanovic void ** pCallStack,
65b146d3b3SDamjan Jovanovic sal_uInt64 * pRegisterReturn /* space for register return */ )
66b146d3b3SDamjan Jovanovic {
67b146d3b3SDamjan Jovanovic // return
68b146d3b3SDamjan Jovanovic typelib_TypeDescription * pReturnTypeDescr = 0;
69b146d3b3SDamjan Jovanovic if (pReturnTypeRef)
70b146d3b3SDamjan Jovanovic TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
71b146d3b3SDamjan Jovanovic
72b146d3b3SDamjan Jovanovic void * pUnoReturn = 0;
73b146d3b3SDamjan Jovanovic void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
74b146d3b3SDamjan Jovanovic
75b146d3b3SDamjan Jovanovic if ( pReturnTypeDescr )
76b146d3b3SDamjan Jovanovic {
77b146d3b3SDamjan Jovanovic if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
78b146d3b3SDamjan Jovanovic {
79b146d3b3SDamjan Jovanovic // complex return via ptr (pCppReturn)
80b146d3b3SDamjan Jovanovic pCppReturn = pCallStack[2];
81b146d3b3SDamjan Jovanovic ++pCallStack;
82b146d3b3SDamjan Jovanovic
83b146d3b3SDamjan Jovanovic pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
84b146d3b3SDamjan Jovanovic ? alloca( pReturnTypeDescr->nSize )
85b146d3b3SDamjan Jovanovic : pCppReturn ); // direct way
86b146d3b3SDamjan Jovanovic }
87b146d3b3SDamjan Jovanovic else
88b146d3b3SDamjan Jovanovic pUnoReturn = pRegisterReturn; // direct way for simple types
89b146d3b3SDamjan Jovanovic }
90b146d3b3SDamjan Jovanovic
91b146d3b3SDamjan Jovanovic // skip to first argument
92b146d3b3SDamjan Jovanovic pCallStack += 2;
93b146d3b3SDamjan Jovanovic
94b146d3b3SDamjan Jovanovic // stack space
95b146d3b3SDamjan Jovanovic // parameters
96b146d3b3SDamjan Jovanovic void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
97b146d3b3SDamjan Jovanovic void ** pCppArgs = pUnoArgs + nParams;
98b146d3b3SDamjan Jovanovic // indices of values this have to be converted (interface conversion cpp<=>uno)
99b146d3b3SDamjan Jovanovic sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
100b146d3b3SDamjan Jovanovic // type descriptions for reconversions
101b146d3b3SDamjan Jovanovic typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
102b146d3b3SDamjan Jovanovic
103b146d3b3SDamjan Jovanovic sal_Int32 nTempIndizes = 0;
104b146d3b3SDamjan Jovanovic
105b146d3b3SDamjan Jovanovic for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
106b146d3b3SDamjan Jovanovic {
107b146d3b3SDamjan Jovanovic const typelib_MethodParameter & rParam = pParams[nPos];
108b146d3b3SDamjan Jovanovic typelib_TypeDescription * pParamTypeDescr = 0;
109b146d3b3SDamjan Jovanovic TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
110b146d3b3SDamjan Jovanovic
111b146d3b3SDamjan Jovanovic if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) // value
112b146d3b3SDamjan Jovanovic {
113b146d3b3SDamjan Jovanovic pCppArgs[nPos] = pUnoArgs[nPos] = pCallStack++;
114b146d3b3SDamjan Jovanovic // no longer needed
115b146d3b3SDamjan Jovanovic TYPELIB_DANGER_RELEASE( pParamTypeDescr );
116b146d3b3SDamjan Jovanovic }
117b146d3b3SDamjan Jovanovic else // ptr to complex value || ref
118b146d3b3SDamjan Jovanovic {
119b146d3b3SDamjan Jovanovic void *pCppStack;
120b146d3b3SDamjan Jovanovic pCppArgs[nPos] = pCppStack = *pCallStack++;
121b146d3b3SDamjan Jovanovic
122b146d3b3SDamjan Jovanovic if (! rParam.bIn) // is pure out
123b146d3b3SDamjan Jovanovic {
124b146d3b3SDamjan Jovanovic // uno out is unconstructed mem!
125b146d3b3SDamjan Jovanovic pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
126b146d3b3SDamjan Jovanovic pTempIndizes[nTempIndizes] = nPos;
127b146d3b3SDamjan Jovanovic // will be released at reconversion
128b146d3b3SDamjan Jovanovic ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
129b146d3b3SDamjan Jovanovic }
130b146d3b3SDamjan Jovanovic else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ) ) // is in/inout
131b146d3b3SDamjan Jovanovic {
132b146d3b3SDamjan Jovanovic uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
133b146d3b3SDamjan Jovanovic pCppStack, pParamTypeDescr,
134b146d3b3SDamjan Jovanovic pThis->getBridge()->getCpp2Uno() );
135b146d3b3SDamjan Jovanovic pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
136b146d3b3SDamjan Jovanovic // will be released at reconversion
137b146d3b3SDamjan Jovanovic ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
138b146d3b3SDamjan Jovanovic }
139b146d3b3SDamjan Jovanovic else // direct way
140b146d3b3SDamjan Jovanovic {
141b146d3b3SDamjan Jovanovic pUnoArgs[nPos] = pCppStack;
142b146d3b3SDamjan Jovanovic // no longer needed
143b146d3b3SDamjan Jovanovic TYPELIB_DANGER_RELEASE( pParamTypeDescr );
144b146d3b3SDamjan Jovanovic }
145b146d3b3SDamjan Jovanovic }
146b146d3b3SDamjan Jovanovic }
147b146d3b3SDamjan Jovanovic
148b146d3b3SDamjan Jovanovic // ExceptionHolder
149b146d3b3SDamjan Jovanovic uno_Any aUnoExc; // Any will be constructed by callee
150b146d3b3SDamjan Jovanovic uno_Any * pUnoExc = &aUnoExc;
151b146d3b3SDamjan Jovanovic
152b146d3b3SDamjan Jovanovic // invoke uno dispatch call
153b146d3b3SDamjan Jovanovic (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
154b146d3b3SDamjan Jovanovic
155b146d3b3SDamjan Jovanovic // in case an exception occurred...
156b146d3b3SDamjan Jovanovic if ( pUnoExc )
157b146d3b3SDamjan Jovanovic {
158b146d3b3SDamjan Jovanovic // destruct temporary in/inout params
159b146d3b3SDamjan Jovanovic for ( ; nTempIndizes--; )
160b146d3b3SDamjan Jovanovic {
161b146d3b3SDamjan Jovanovic sal_Int32 nIndex = pTempIndizes[nTempIndizes];
162b146d3b3SDamjan Jovanovic
163b146d3b3SDamjan Jovanovic if (pParams[nIndex].bIn) // is in/inout => was constructed
164b146d3b3SDamjan Jovanovic uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
165b146d3b3SDamjan Jovanovic TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
166b146d3b3SDamjan Jovanovic }
167b146d3b3SDamjan Jovanovic if (pReturnTypeDescr)
168b146d3b3SDamjan Jovanovic TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
169b146d3b3SDamjan Jovanovic
170b146d3b3SDamjan Jovanovic CPPU_CURRENT_NAMESPACE::mscx_raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
171b146d3b3SDamjan Jovanovic // is here for dummy
172b146d3b3SDamjan Jovanovic return typelib_TypeClass_VOID;
173b146d3b3SDamjan Jovanovic }
174b146d3b3SDamjan Jovanovic else // else no exception occurred...
175b146d3b3SDamjan Jovanovic {
176b146d3b3SDamjan Jovanovic // temporary params
177b146d3b3SDamjan Jovanovic for ( ; nTempIndizes--; )
178b146d3b3SDamjan Jovanovic {
179b146d3b3SDamjan Jovanovic sal_Int32 nIndex = pTempIndizes[nTempIndizes];
180b146d3b3SDamjan Jovanovic typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
181b146d3b3SDamjan Jovanovic
182b146d3b3SDamjan Jovanovic if ( pParams[nIndex].bOut ) // inout/out
183b146d3b3SDamjan Jovanovic {
184b146d3b3SDamjan Jovanovic // convert and assign
185b146d3b3SDamjan Jovanovic uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
186b146d3b3SDamjan Jovanovic uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
187b146d3b3SDamjan Jovanovic pThis->getBridge()->getUno2Cpp() );
188b146d3b3SDamjan Jovanovic }
189b146d3b3SDamjan Jovanovic // destroy temp uno param
190b146d3b3SDamjan Jovanovic uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
191b146d3b3SDamjan Jovanovic
192b146d3b3SDamjan Jovanovic TYPELIB_DANGER_RELEASE( pParamTypeDescr );
193b146d3b3SDamjan Jovanovic }
194b146d3b3SDamjan Jovanovic // return
195b146d3b3SDamjan Jovanovic if ( pCppReturn ) // has complex return
196b146d3b3SDamjan Jovanovic {
197b146d3b3SDamjan Jovanovic if ( pUnoReturn != pCppReturn ) // needs reconversion
198b146d3b3SDamjan Jovanovic {
199b146d3b3SDamjan Jovanovic uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
200b146d3b3SDamjan Jovanovic pThis->getBridge()->getUno2Cpp() );
201b146d3b3SDamjan Jovanovic // destroy temp uno return
202b146d3b3SDamjan Jovanovic uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
203b146d3b3SDamjan Jovanovic }
204b146d3b3SDamjan Jovanovic // complex return ptr is set to rax
205b146d3b3SDamjan Jovanovic *(void **)pRegisterReturn = pCppReturn;
206b146d3b3SDamjan Jovanovic }
207b146d3b3SDamjan Jovanovic if ( pReturnTypeDescr )
208b146d3b3SDamjan Jovanovic {
209b146d3b3SDamjan Jovanovic typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
210b146d3b3SDamjan Jovanovic TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
211b146d3b3SDamjan Jovanovic return eRet;
212b146d3b3SDamjan Jovanovic }
213b146d3b3SDamjan Jovanovic else
214b146d3b3SDamjan Jovanovic return typelib_TypeClass_VOID;
215b146d3b3SDamjan Jovanovic }
216b146d3b3SDamjan Jovanovic }
217b146d3b3SDamjan Jovanovic
218b146d3b3SDamjan Jovanovic
219b146d3b3SDamjan Jovanovic //==================================================================================================
cpp_vtable_call(void ** pCallStack,sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,sal_uInt64 * pRegisterReturn)220b146d3b3SDamjan Jovanovic extern "C" typelib_TypeClass cpp_vtable_call(
221b146d3b3SDamjan Jovanovic void ** pCallStack, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
222b146d3b3SDamjan Jovanovic sal_uInt64 * pRegisterReturn /* space for register return */ )
223b146d3b3SDamjan Jovanovic {
224b146d3b3SDamjan Jovanovic // pCallStack: ret adr, this, [ret *], params
225b146d3b3SDamjan Jovanovic void * pThis = static_cast< char * >(pCallStack[1]) - nVtableOffset;
226b146d3b3SDamjan Jovanovic
227b146d3b3SDamjan Jovanovic bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
228b146d3b3SDamjan Jovanovic bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis );
229b146d3b3SDamjan Jovanovic
230b146d3b3SDamjan Jovanovic typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
231b146d3b3SDamjan Jovanovic
232b146d3b3SDamjan Jovanovic OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
233b146d3b3SDamjan Jovanovic if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex )
234b146d3b3SDamjan Jovanovic {
235b146d3b3SDamjan Jovanovic throw RuntimeException( OUString::createFromAscii("illegal vtable index!"),
236b146d3b3SDamjan Jovanovic reinterpret_cast<XInterface *>( pCppI ) );
237b146d3b3SDamjan Jovanovic }
238b146d3b3SDamjan Jovanovic
239b146d3b3SDamjan Jovanovic // determine called method
240b146d3b3SDamjan Jovanovic sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
241b146d3b3SDamjan Jovanovic OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
242b146d3b3SDamjan Jovanovic
243b146d3b3SDamjan Jovanovic TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
244b146d3b3SDamjan Jovanovic
245b146d3b3SDamjan Jovanovic typelib_TypeClass eRet;
246b146d3b3SDamjan Jovanovic switch ( aMemberDescr.get()->eTypeClass )
247b146d3b3SDamjan Jovanovic {
248b146d3b3SDamjan Jovanovic case typelib_TypeClass_INTERFACE_ATTRIBUTE:
249b146d3b3SDamjan Jovanovic {
250b146d3b3SDamjan Jovanovic typelib_TypeDescriptionReference *pAttrTypeRef =
251b146d3b3SDamjan Jovanovic reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef;
252b146d3b3SDamjan Jovanovic
253b146d3b3SDamjan Jovanovic if ( pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
254b146d3b3SDamjan Jovanovic {
255b146d3b3SDamjan Jovanovic // is GET method
256b146d3b3SDamjan Jovanovic eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef,
257b146d3b3SDamjan Jovanovic 0, 0, // no params
258b146d3b3SDamjan Jovanovic pCallStack, pRegisterReturn );
259b146d3b3SDamjan Jovanovic }
260b146d3b3SDamjan Jovanovic else
261b146d3b3SDamjan Jovanovic {
262b146d3b3SDamjan Jovanovic // is SET method
263b146d3b3SDamjan Jovanovic typelib_MethodParameter aParam;
264b146d3b3SDamjan Jovanovic aParam.pTypeRef = pAttrTypeRef;
265b146d3b3SDamjan Jovanovic aParam.bIn = sal_True;
266b146d3b3SDamjan Jovanovic aParam.bOut = sal_False;
267b146d3b3SDamjan Jovanovic
268b146d3b3SDamjan Jovanovic eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
269b146d3b3SDamjan Jovanovic 0, // indicates void return
270b146d3b3SDamjan Jovanovic 1, &aParam,
271b146d3b3SDamjan Jovanovic pCallStack, pRegisterReturn );
272b146d3b3SDamjan Jovanovic }
273b146d3b3SDamjan Jovanovic break;
274b146d3b3SDamjan Jovanovic }
275b146d3b3SDamjan Jovanovic case typelib_TypeClass_INTERFACE_METHOD:
276b146d3b3SDamjan Jovanovic {
277b146d3b3SDamjan Jovanovic // is METHOD
278b146d3b3SDamjan Jovanovic switch ( nFunctionIndex )
279b146d3b3SDamjan Jovanovic {
280b146d3b3SDamjan Jovanovic // standard XInterface vtable calls
281b146d3b3SDamjan Jovanovic case 1: // acquire()
282b146d3b3SDamjan Jovanovic pCppI->acquireProxy(); // non virtual call!
283b146d3b3SDamjan Jovanovic eRet = typelib_TypeClass_VOID;
284b146d3b3SDamjan Jovanovic break;
285b146d3b3SDamjan Jovanovic case 2: // release()
286b146d3b3SDamjan Jovanovic pCppI->releaseProxy(); // non virtual call!
287b146d3b3SDamjan Jovanovic eRet = typelib_TypeClass_VOID;
288b146d3b3SDamjan Jovanovic break;
289b146d3b3SDamjan Jovanovic case 0: // queryInterface() opt
290b146d3b3SDamjan Jovanovic {
291b146d3b3SDamjan Jovanovic typelib_TypeDescription * pTD = 0;
292b146d3b3SDamjan Jovanovic TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( pCallStack[3] )->getTypeLibType() );
293b146d3b3SDamjan Jovanovic if ( pTD )
294b146d3b3SDamjan Jovanovic {
295b146d3b3SDamjan Jovanovic XInterface * pInterface = 0;
296b146d3b3SDamjan Jovanovic (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
297b146d3b3SDamjan Jovanovic ( pCppI->getBridge()->getCppEnv(),
298b146d3b3SDamjan Jovanovic (void **)&pInterface,
299b146d3b3SDamjan Jovanovic pCppI->getOid().pData,
300b146d3b3SDamjan Jovanovic reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
301b146d3b3SDamjan Jovanovic
302b146d3b3SDamjan Jovanovic if ( pInterface )
303b146d3b3SDamjan Jovanovic {
304b146d3b3SDamjan Jovanovic ::uno_any_construct( reinterpret_cast<uno_Any *>( pCallStack[1] ),
305b146d3b3SDamjan Jovanovic &pInterface, pTD, cpp_acquire );
306b146d3b3SDamjan Jovanovic
307b146d3b3SDamjan Jovanovic pInterface->release();
308b146d3b3SDamjan Jovanovic TYPELIB_DANGER_RELEASE( pTD );
309b146d3b3SDamjan Jovanovic
310b146d3b3SDamjan Jovanovic reinterpret_cast<void **>( pRegisterReturn )[0] = pCallStack[1];
311b146d3b3SDamjan Jovanovic eRet = typelib_TypeClass_ANY;
312b146d3b3SDamjan Jovanovic break;
313b146d3b3SDamjan Jovanovic }
314b146d3b3SDamjan Jovanovic TYPELIB_DANGER_RELEASE( pTD );
315b146d3b3SDamjan Jovanovic }
316b146d3b3SDamjan Jovanovic } // else perform queryInterface()
317b146d3b3SDamjan Jovanovic default:
318b146d3b3SDamjan Jovanovic {
319b146d3b3SDamjan Jovanovic typelib_InterfaceMethodTypeDescription *pMethodTD =
320b146d3b3SDamjan Jovanovic reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
321b146d3b3SDamjan Jovanovic
322b146d3b3SDamjan Jovanovic eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
323b146d3b3SDamjan Jovanovic pMethodTD->pReturnTypeRef,
324b146d3b3SDamjan Jovanovic pMethodTD->nParams,
325b146d3b3SDamjan Jovanovic pMethodTD->pParams,
326b146d3b3SDamjan Jovanovic pCallStack, pRegisterReturn );
327b146d3b3SDamjan Jovanovic }
328b146d3b3SDamjan Jovanovic }
329b146d3b3SDamjan Jovanovic break;
330b146d3b3SDamjan Jovanovic }
331b146d3b3SDamjan Jovanovic default:
332b146d3b3SDamjan Jovanovic {
333b146d3b3SDamjan Jovanovic throw RuntimeException( OUString::createFromAscii("no member description found!"),
334b146d3b3SDamjan Jovanovic reinterpret_cast<XInterface *>( pCppI ) );
335b146d3b3SDamjan Jovanovic // is here for dummy
336b146d3b3SDamjan Jovanovic eRet = typelib_TypeClass_VOID;
337b146d3b3SDamjan Jovanovic }
338b146d3b3SDamjan Jovanovic }
339b146d3b3SDamjan Jovanovic
340b146d3b3SDamjan Jovanovic return eRet;
341b146d3b3SDamjan Jovanovic }
342b146d3b3SDamjan Jovanovic
343b146d3b3SDamjan Jovanovic //==================================================================================================
344b146d3b3SDamjan Jovanovic extern "C" void privateSnippetExecutor( ... );
345b146d3b3SDamjan Jovanovic
346b146d3b3SDamjan Jovanovic int const codeSnippetSize = 44;
347b146d3b3SDamjan Jovanovic
codeSnippet(unsigned char * code,sal_Int32 functionIndex,sal_Int32 vtableOffset,bool isArgFloat[4])348b146d3b3SDamjan Jovanovic unsigned char * codeSnippet(
349b146d3b3SDamjan Jovanovic unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, bool isArgFloat[4])
350b146d3b3SDamjan Jovanovic {
351b146d3b3SDamjan Jovanovic unsigned char * p = code;
352b146d3b3SDamjan Jovanovic
353b146d3b3SDamjan Jovanovic
354b146d3b3SDamjan Jovanovic //
355b146d3b3SDamjan Jovanovic // | ... |
356b146d3b3SDamjan Jovanovic // +----------------------------+
357b146d3b3SDamjan Jovanovic // | argument 4 |
358b146d3b3SDamjan Jovanovic // rsp+40 +----------------------------+ -------
359b146d3b3SDamjan Jovanovic // | argument 3, r9/xmm3 home | ^ shadow
360b146d3b3SDamjan Jovanovic // rsp+32 +----------------------------+ | space,
361b146d3b3SDamjan Jovanovic // | argument 2, r8/xmm2 home | | guaranteed to be present but uninitialized,
362b146d3b3SDamjan Jovanovic // rsp+24 +----------------------------+ | we have to copy
363b146d3b3SDamjan Jovanovic // | argument 1, rdx/xmm1 home | | the first 4 parameters there from the registers,
364b146d3b3SDamjan Jovanovic // rsp+16 +----------------------------+ | to form the continuous array of arguments.
365b146d3b3SDamjan Jovanovic // | argument 0, rcx/xmm0 home | v
366b146d3b3SDamjan Jovanovic // rsp+08 +----------------------------+ -------
367b146d3b3SDamjan Jovanovic // | return address |
368b146d3b3SDamjan Jovanovic // rsp--> +----------------------------+
369b146d3b3SDamjan Jovanovic //
370b146d3b3SDamjan Jovanovic //
371b146d3b3SDamjan Jovanovic
372b146d3b3SDamjan Jovanovic if (isArgFloat[0])
373b146d3b3SDamjan Jovanovic {
374b146d3b3SDamjan Jovanovic // movsd QWORD[rsp+8], XMM0
375b146d3b3SDamjan Jovanovic *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x44; *p++ = 0x24; *p++ = 0x08;
376b146d3b3SDamjan Jovanovic }
377b146d3b3SDamjan Jovanovic else
378b146d3b3SDamjan Jovanovic {
379b146d3b3SDamjan Jovanovic // mov QWORD[rsp+8], rcx
380b146d3b3SDamjan Jovanovic *p++ = 0x48; *p++ = 0x49; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x08;
381b146d3b3SDamjan Jovanovic }
382b146d3b3SDamjan Jovanovic
383b146d3b3SDamjan Jovanovic if (isArgFloat[1])
384b146d3b3SDamjan Jovanovic {
385b146d3b3SDamjan Jovanovic // movsd QWORD[rsp+16], XMM1
386b146d3b3SDamjan Jovanovic *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x10;
387b146d3b3SDamjan Jovanovic }
388b146d3b3SDamjan Jovanovic else
389b146d3b3SDamjan Jovanovic {
390b146d3b3SDamjan Jovanovic // mov QWORD[rsp+16], rdx
391b146d3b3SDamjan Jovanovic *p++ = 0x48; *p++ = 0x49; *p++ = 0x54; *p++ = 0x24; *p++ = 0x10;
392b146d3b3SDamjan Jovanovic }
393b146d3b3SDamjan Jovanovic
394b146d3b3SDamjan Jovanovic if (isArgFloat[2])
395b146d3b3SDamjan Jovanovic {
396b146d3b3SDamjan Jovanovic // movsd QWORD[rsp+24], XMM2
397b146d3b3SDamjan Jovanovic *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x54; *p++ = 0x24; *p++ = 0x18;
398b146d3b3SDamjan Jovanovic }
399b146d3b3SDamjan Jovanovic else
400b146d3b3SDamjan Jovanovic {
401b146d3b3SDamjan Jovanovic // mov QWORD[rsp+24], r8
402b146d3b3SDamjan Jovanovic *p++ = 0x4c; *p++ = 0x89; *p++ = 0x44; *p++ = 0x24; *p++ = 0x18;
403b146d3b3SDamjan Jovanovic }
404b146d3b3SDamjan Jovanovic
405b146d3b3SDamjan Jovanovic if (isArgFloat[3])
406b146d3b3SDamjan Jovanovic {
407b146d3b3SDamjan Jovanovic // movsd QWORD[rsp+32], XMM3
408b146d3b3SDamjan Jovanovic *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x5c; *p++ = 0x24; *p++ = 0x20;
409b146d3b3SDamjan Jovanovic }
410b146d3b3SDamjan Jovanovic else
411b146d3b3SDamjan Jovanovic {
412b146d3b3SDamjan Jovanovic // mov QWORD[rsp+32], r9
413b146d3b3SDamjan Jovanovic *p++ = 0x4c; *p++ = 0x89; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x20;
414b146d3b3SDamjan Jovanovic }
415b146d3b3SDamjan Jovanovic
416b146d3b3SDamjan Jovanovic // mov rax, functionIndex
417b146d3b3SDamjan Jovanovic *p++ = 0xb8;
418b146d3b3SDamjan Jovanovic *p++ = functionIndex & 0xff;
419b146d3b3SDamjan Jovanovic *p++ = (functionIndex >> 8) & 0xff;
420b146d3b3SDamjan Jovanovic *p++ = (functionIndex >> 16) & 0xff;
421b146d3b3SDamjan Jovanovic *p++ = (functionIndex >> 24) & 0xff;
422b146d3b3SDamjan Jovanovic
423b146d3b3SDamjan Jovanovic // mov r10, vtableOffset
424b146d3b3SDamjan Jovanovic *p++ = 0x41;
425b146d3b3SDamjan Jovanovic *p++ = 0xba;
426b146d3b3SDamjan Jovanovic *p++ = vtableOffset & 0xff;
427b146d3b3SDamjan Jovanovic *p++ = (vtableOffset >> 8) & 0xff;
428b146d3b3SDamjan Jovanovic *p++ = (vtableOffset >> 16) & 0xff;
429b146d3b3SDamjan Jovanovic *p++ = (vtableOffset >> 24) & 0xff;
430b146d3b3SDamjan Jovanovic
431b146d3b3SDamjan Jovanovic // mov r11, privateSnippetExecutor
432b146d3b3SDamjan Jovanovic *p++ = 0x49;
433b146d3b3SDamjan Jovanovic *p++ = 0xbb;
434b146d3b3SDamjan Jovanovic *p++ = ((sal_uIntPtr)(&privateSnippetExecutor)) & 0xff;
435b146d3b3SDamjan Jovanovic *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 8) & 0xff;
436b146d3b3SDamjan Jovanovic *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 16) & 0xff;
437b146d3b3SDamjan Jovanovic *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 24) & 0xff;
438b146d3b3SDamjan Jovanovic *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 32) & 0xff;
439b146d3b3SDamjan Jovanovic *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 40) & 0xff;
440b146d3b3SDamjan Jovanovic *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 48) & 0xff;
441b146d3b3SDamjan Jovanovic *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 56) & 0xff;
442b146d3b3SDamjan Jovanovic
443b146d3b3SDamjan Jovanovic // jmp r11
444b146d3b3SDamjan Jovanovic *p++ = 0x49;
445b146d3b3SDamjan Jovanovic *p++ = 0xff;
446b146d3b3SDamjan Jovanovic *p++ = 0xe3;
447b146d3b3SDamjan Jovanovic
448b146d3b3SDamjan Jovanovic OSL_ASSERT(p - code <= codeSnippetSize);
449b146d3b3SDamjan Jovanovic return code + codeSnippetSize;
450b146d3b3SDamjan Jovanovic }
451b146d3b3SDamjan Jovanovic
452b146d3b3SDamjan Jovanovic }
453b146d3b3SDamjan Jovanovic
454b146d3b3SDamjan Jovanovic struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
455b146d3b3SDamjan Jovanovic
456b146d3b3SDamjan Jovanovic bridges::cpp_uno::shared::VtableFactory::Slot *
mapBlockToVtable(void * block)457b146d3b3SDamjan Jovanovic bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
458b146d3b3SDamjan Jovanovic {
459b146d3b3SDamjan Jovanovic return static_cast< Slot * >(block) + 1;
460b146d3b3SDamjan Jovanovic }
461b146d3b3SDamjan Jovanovic
getBlockSize(sal_Int32 slotCount)462b146d3b3SDamjan Jovanovic sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
463b146d3b3SDamjan Jovanovic sal_Int32 slotCount)
464b146d3b3SDamjan Jovanovic {
465b146d3b3SDamjan Jovanovic return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize;
466b146d3b3SDamjan Jovanovic }
467b146d3b3SDamjan Jovanovic
468b146d3b3SDamjan Jovanovic bridges::cpp_uno::shared::VtableFactory::Slot *
initializeBlock(void * block,sal_Int32 slotCount)469b146d3b3SDamjan Jovanovic bridges::cpp_uno::shared::VtableFactory::initializeBlock(
470b146d3b3SDamjan Jovanovic void * block, sal_Int32 slotCount)
471b146d3b3SDamjan Jovanovic {
472b146d3b3SDamjan Jovanovic struct RttiCompleteObjectLocator {
473b146d3b3SDamjan Jovanovic sal_uInt32 signature;
474b146d3b3SDamjan Jovanovic sal_uInt32 offset; // offset of vtable in objects of the class
475b146d3b3SDamjan Jovanovic sal_uInt32 cdOffset; // constructor displacement offset
476b146d3b3SDamjan Jovanovic // On AMD64, these 2 are offsets from the module's base address (when signature == 0):
477b146d3b3SDamjan Jovanovic sal_uInt32 typeDescriptorAddress;
478b146d3b3SDamjan Jovanovic sal_uInt32 classDescriptorAddress;
479b146d3b3SDamjan Jovanovic sal_uInt32 objectBase; // ignored when signature == 0
480b146d3b3SDamjan Jovanovic
481b146d3b3SDamjan Jovanovic RttiCompleteObjectLocator(): signature(0), offset(0), cdOffset(0)
482b146d3b3SDamjan Jovanovic {
483b146d3b3SDamjan Jovanovic type_info *typeInfo = CPPU_CURRENT_NAMESPACE::mscx_getRTTI(
484b146d3b3SDamjan Jovanovic rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
485b146d3b3SDamjan Jovanovic "com.sun.star.uno.XInterface")));
486b146d3b3SDamjan Jovanovic HMODULE thisDLLBase;
487b146d3b3SDamjan Jovanovic GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)&bridges::cpp_uno::shared::VtableFactory::initializeBlock, &thisDLLBase);
488b146d3b3SDamjan Jovanovic typeDescriptorAddress = (sal_uInt32) (((char*)typeInfo) - (char*)thisDLLBase);
489b146d3b3SDamjan Jovanovic classDescriptorAddress = 0;
490b146d3b3SDamjan Jovanovic objectBase = 0;
491b146d3b3SDamjan Jovanovic }
492b146d3b3SDamjan Jovanovic };
493b146d3b3SDamjan Jovanovic static RttiCompleteObjectLocator rtti;
494b146d3b3SDamjan Jovanovic
495b146d3b3SDamjan Jovanovic Slot * slots = mapBlockToVtable(block);
496b146d3b3SDamjan Jovanovic slots[-1].fn = &rtti;
497b146d3b3SDamjan Jovanovic return slots + slotCount;
498b146d3b3SDamjan Jovanovic }
499b146d3b3SDamjan Jovanovic
findFirst4Win64ArgumentTypes(typelib_MethodParameter * pParams,sal_Int32 nParams,typelib_TypeDescriptionReference * pReturnType,bool isArgFloat[4])500b146d3b3SDamjan Jovanovic static void findFirst4Win64ArgumentTypes(
501b146d3b3SDamjan Jovanovic typelib_MethodParameter *pParams, sal_Int32 nParams,
502b146d3b3SDamjan Jovanovic typelib_TypeDescriptionReference *pReturnType, bool isArgFloat[4])
503b146d3b3SDamjan Jovanovic {
504b146d3b3SDamjan Jovanovic sal_uInt32 index = 0;
505b146d3b3SDamjan Jovanovic
506b146d3b3SDamjan Jovanovic isArgFloat[0] = isArgFloat[1] = isArgFloat[2] = isArgFloat[3] = false;
507b146d3b3SDamjan Jovanovic
508b146d3b3SDamjan Jovanovic // C++ "this" pointer:
509b146d3b3SDamjan Jovanovic ++index;
510b146d3b3SDamjan Jovanovic
511b146d3b3SDamjan Jovanovic // https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2017
512b146d3b3SDamjan Jovanovic // "Otherwise the caller assumes the responsibility of allocating memory
513b146d3b3SDamjan Jovanovic // and passing a pointer for the return value as the first argument.
514b146d3b3SDamjan Jovanovic // Subsequent arguments are then shifted one argument to the right.
515b146d3b3SDamjan Jovanovic // The same pointer must be returned by the callee in RAX."
516b146d3b3SDamjan Jovanovic if ( pReturnType && x86_64::return_in_hidden_param( pReturnType ) )
517b146d3b3SDamjan Jovanovic ++index;
518b146d3b3SDamjan Jovanovic
519b146d3b3SDamjan Jovanovic for (int param = 0; param < nParams; param++)
520b146d3b3SDamjan Jovanovic {
521b146d3b3SDamjan Jovanovic if (index >= 4)
522b146d3b3SDamjan Jovanovic break;
523b146d3b3SDamjan Jovanovic
524b146d3b3SDamjan Jovanovic typelib_TypeDescription *pParamTypeDescr = 0;
525b146d3b3SDamjan Jovanovic
526b146d3b3SDamjan Jovanovic TYPELIB_DANGER_GET( &pParamTypeDescr, pParams[param].pTypeRef );
527b146d3b3SDamjan Jovanovic OSL_ASSERT( pParamTypeDescr );
528b146d3b3SDamjan Jovanovic
529b146d3b3SDamjan Jovanovic isArgFloat[index++] = !pParams[param].bOut &&
530b146d3b3SDamjan Jovanovic (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT ||
531b146d3b3SDamjan Jovanovic pParamTypeDescr->eTypeClass == typelib_TypeClass_DOUBLE);
532b146d3b3SDamjan Jovanovic
533b146d3b3SDamjan Jovanovic TYPELIB_DANGER_RELEASE( pParamTypeDescr );
534b146d3b3SDamjan Jovanovic }
535b146d3b3SDamjan Jovanovic }
536b146d3b3SDamjan Jovanovic
addLocalFunctions(Slot ** slots,unsigned char * code,typelib_InterfaceTypeDescription const * type,sal_Int32 functionOffset,sal_Int32 functionCount,sal_Int32 vtableOffset)537b146d3b3SDamjan Jovanovic unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
538b146d3b3SDamjan Jovanovic Slot ** slots, unsigned char * code,
539b146d3b3SDamjan Jovanovic typelib_InterfaceTypeDescription const *type, sal_Int32 functionOffset,
540b146d3b3SDamjan Jovanovic sal_Int32 functionCount, sal_Int32 vtableOffset)
541b146d3b3SDamjan Jovanovic {
542b146d3b3SDamjan Jovanovic (*slots) -= functionCount;
543b146d3b3SDamjan Jovanovic Slot * s = *slots;
544b146d3b3SDamjan Jovanovic for (sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos) {
545b146d3b3SDamjan Jovanovic typelib_TypeDescription * pTD = 0;
546b146d3b3SDamjan Jovanovic
547b146d3b3SDamjan Jovanovic TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] );
548b146d3b3SDamjan Jovanovic OSL_ASSERT( pTD );
549b146d3b3SDamjan Jovanovic
550b146d3b3SDamjan Jovanovic bool isArgFloat[4];
551b146d3b3SDamjan Jovanovic if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass )
552b146d3b3SDamjan Jovanovic {
553b146d3b3SDamjan Jovanovic typelib_InterfaceAttributeTypeDescription *pAttrTD =
554b146d3b3SDamjan Jovanovic reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
555b146d3b3SDamjan Jovanovic
556b146d3b3SDamjan Jovanovic // get method
557b146d3b3SDamjan Jovanovic findFirst4Win64ArgumentTypes(0, 0, pAttrTD->pAttributeTypeRef, isArgFloat);
558b146d3b3SDamjan Jovanovic (s++)->fn = code;
559b146d3b3SDamjan Jovanovic code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat);
560b146d3b3SDamjan Jovanovic
561b146d3b3SDamjan Jovanovic if ( ! pAttrTD->bReadOnly )
562b146d3b3SDamjan Jovanovic {
563b146d3b3SDamjan Jovanovic // set method
564b146d3b3SDamjan Jovanovic typelib_MethodParameter aParam;
565b146d3b3SDamjan Jovanovic aParam.pTypeRef = pAttrTD->pAttributeTypeRef;
566b146d3b3SDamjan Jovanovic aParam.bIn = sal_True;
567b146d3b3SDamjan Jovanovic aParam.bOut = sal_False;
568b146d3b3SDamjan Jovanovic findFirst4Win64ArgumentTypes(&aParam, 1, 0, isArgFloat);
569b146d3b3SDamjan Jovanovic (s++)->fn = code;
570b146d3b3SDamjan Jovanovic code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat);
571b146d3b3SDamjan Jovanovic }
572b146d3b3SDamjan Jovanovic }
573b146d3b3SDamjan Jovanovic else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass )
574b146d3b3SDamjan Jovanovic {
575b146d3b3SDamjan Jovanovic typelib_InterfaceMethodTypeDescription *pMethodTD =
576b146d3b3SDamjan Jovanovic reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
577b146d3b3SDamjan Jovanovic findFirst4Win64ArgumentTypes(pMethodTD->pParams, pMethodTD->nParams,
578b146d3b3SDamjan Jovanovic pMethodTD->pReturnTypeRef, isArgFloat);
579b146d3b3SDamjan Jovanovic (s++)->fn = code;
580b146d3b3SDamjan Jovanovic code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat);
581b146d3b3SDamjan Jovanovic }
582b146d3b3SDamjan Jovanovic else
583b146d3b3SDamjan Jovanovic OSL_ASSERT( false );
584b146d3b3SDamjan Jovanovic
585b146d3b3SDamjan Jovanovic TYPELIB_DANGER_RELEASE( pTD );
586b146d3b3SDamjan Jovanovic }
587b146d3b3SDamjan Jovanovic return code;
588b146d3b3SDamjan Jovanovic }
589b146d3b3SDamjan Jovanovic
flushCode(unsigned char const *,unsigned char const *)590b146d3b3SDamjan Jovanovic void bridges::cpp_uno::shared::VtableFactory::flushCode(
591b146d3b3SDamjan Jovanovic unsigned char const *, unsigned char const *)
592b146d3b3SDamjan Jovanovic {}
593