LibreOffice Module bridges (master)  1
msvc_win32_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 <malloc.h>
22 
23 #include <com/sun/star/uno/genfunc.hxx>
24 #include <sal/log.hxx>
25 #include <uno/data.h>
26 #include <typelib/typedescription.hxx>
27 
28 #include <bridge.hxx>
29 #include <cppinterfaceproxy.hxx>
30 #include <types.hxx>
31 #include <vtablefactory.hxx>
32 
33 #include "call.hxx"
34 #include <msvc/cpp2uno.hxx>
35 #include <msvc/amd64.hxx>
36 
37 using namespace ::com::sun::star;
38 
39 extern "C" typelib_TypeClass cpp_vtable_call(sal_Int64 nOffsetAndIndex, void ** pCallStack)
40 {
41  sal_Int32 nFunctionIndex = (nOffsetAndIndex & 0xFFFFFFFF);
42  sal_Int32 nVtableOffset = ((nOffsetAndIndex >> 32) & 0xFFFFFFFF);
43  return cpp_mediate(pCallStack, nFunctionIndex, nVtableOffset, nullptr);
44 }
45 
46 int const codeSnippetSize = 48;
47 
48 namespace {
49 
50 typedef enum { REGPARAM_INT, REGPARAM_FLT } RegParamKind;
51 
52 }
53 
54 extern "C" char privateSnippetExecutor;
55 
56 // This function generates the code that acts as a proxy for the UNO function to be called.
57 // The generated code does the following:
58 // - Spills register parameters on stack
59 // - Loads functionIndex and vtableOffset into scratch registers
60 // - Jumps to privateSnippetExecutor
61 
62 static unsigned char * codeSnippet(
63  unsigned char * code,
64  RegParamKind param_kind[4],
65  sal_Int32 nFunctionIndex,
66  sal_Int32 nVtableOffset )
67 {
68  sal_uInt64 nOffsetAndIndex = ( static_cast<sal_uInt64>(nVtableOffset) << 32 ) | static_cast<sal_uInt64>(nFunctionIndex);
69  unsigned char *p = code;
70 
71  // Spill parameters
72  if (param_kind[0] == REGPARAM_INT)
73  {
74  // mov qword ptr 8[rsp], rcx
75  *p++ = 0x48; *p++ = 0x89; *p++ = 0x4C; *p++ = 0x24; *p++ = 0x08;
76  }
77  else
78  {
79  // movsd qword ptr 8[rsp], xmm0
80  *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x44; *p++ = 0x24; *p++ = 0x08;
81  }
82  if ( param_kind[1] == REGPARAM_INT )
83  {
84  // mov qword ptr 16[rsp], rdx
85  *p++ = 0x48; *p++ = 0x89; *p++ = 0x54; *p++ = 0x24; *p++ = 0x10;
86  }
87  else
88  {
89  // movsd qword ptr 16[rsp], xmm1
90  *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x4C; *p++ = 0x24; *p++ = 0x10;
91  }
92  if ( param_kind[2] == REGPARAM_INT )
93  {
94  // mov qword ptr 24[rsp], r8
95  *p++ = 0x4C; *p++ = 0x89; *p++ = 0x44; *p++ = 0x24; *p++ = 0x18;
96  }
97  else
98  {
99  // movsd qword ptr 24[rsp], xmm2
100  *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x54; *p++ = 0x24; *p++ = 0x18;
101  }
102  if ( param_kind[3] == REGPARAM_INT )
103  {
104  // mov qword ptr 32[rsp], r9
105  *p++ = 0x4C;*p++ = 0x89; *p++ = 0x4C; *p++ = 0x24; *p++ = 0x20;
106  }
107  else
108  {
109  // movsd qword ptr 32[rsp], xmm3
110  *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x5C; *p++ = 0x24; *p++ = 0x20;
111  }
112 
113  // mov rcx, nOffsetAndIndex
114  *p++ = 0x48; *p++ = 0xB9;
115  *reinterpret_cast<sal_uInt64 *>(p) = nOffsetAndIndex; p += 8;
116 
117  // mov r11, privateSnippetExecutor
118  *p++ = 0x49; *p++ = 0xBB;
119  *reinterpret_cast<void **>(p) = &privateSnippetExecutor; p += 8;
120 
121  // jmp r11
122  *p++ = 0x41; *p++ = 0xFF; *p++ = 0xE3;
123 
124  assert(p < code + codeSnippetSize);
125 
126  return code + codeSnippetSize;
127 }
128 
130 
133  void * block )
134 {
135  return static_cast< Slot * >(block) + 1;
136 }
137 
139  sal_Int32 slotCount)
140 {
141  return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize;
142 }
143 
146  void * block,
147  sal_Int32 slotCount,
148  sal_Int32, typelib_InterfaceTypeDescription *)
149 {
150  struct Rtti {
151  sal_Int32 n0, n1, n2;
152  type_info * rtti;
153  Rtti():
154  n0(0), n1(0), n2(0),
155  rtti(RTTInfos::get("com.sun.star.uno.XInterface"))
156  {}
157  };
158  static Rtti rtti;
159 
160  Slot * slots = mapBlockToVtable(block);
161  slots[-1].fn = &rtti;
162  return slots + slotCount;
163 }
164 
166  Slot ** slots,
167  unsigned char * code,
168  typelib_InterfaceTypeDescription const * type,
169  sal_Int32 nFunctionOffset,
170  sal_Int32 functionCount,
171  sal_Int32 nVtableOffset )
172 {
173  (*slots) -= functionCount;
174  Slot * s = *slots;
175 
176  for (int member = 0; member < type->nMembers; ++member) {
177  typelib_TypeDescription * pTD = nullptr;
178 
179  TYPELIB_DANGER_GET( &pTD, type->ppMembers[ member ] );
180  assert(pTD);
181 
182  RegParamKind param_kind[4];
183  int nr = 0;
184 
185  for (int i = 0; i < 4; ++i)
186  param_kind[i] = REGPARAM_INT;
187 
188  // 'this'
189  ++nr;
190 
191  if ( pTD->eTypeClass == typelib_TypeClass_INTERFACE_ATTRIBUTE )
192  {
193  typelib_InterfaceAttributeTypeDescription * pIfaceAttrTD =
194  reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
195 
196  // Getter
197 
198  (s++)->fn = code;
199  code = codeSnippet( code, param_kind, nFunctionOffset++, nVtableOffset );
200  if ( ! pIfaceAttrTD->bReadOnly )
201  {
202  typelib_TypeDescription * pAttrTD = nullptr;
203  TYPELIB_DANGER_GET( &pAttrTD, pIfaceAttrTD->pAttributeTypeRef );
204  assert(pAttrTD);
205 
206  // Setter
207  if ( pAttrTD->eTypeClass == typelib_TypeClass_FLOAT ||
208  pAttrTD->eTypeClass == typelib_TypeClass_DOUBLE )
209  param_kind[nr++] = REGPARAM_FLT;
210 
211  TYPELIB_DANGER_RELEASE( pAttrTD );
212 
213  (s++)->fn = code;
214  code = codeSnippet( code, param_kind, nFunctionOffset++, nVtableOffset );
215  }
216  }
217  else if ( pTD->eTypeClass == typelib_TypeClass_INTERFACE_METHOD )
218  {
219  typelib_InterfaceMethodTypeDescription * pMethodTD =
220  reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
221 
222  typelib_TypeDescription * pReturnTD = nullptr;
223  TYPELIB_DANGER_GET( &pReturnTD, pMethodTD->pReturnTypeRef );
224  assert(pReturnTD);
225 
226  if ( !bridges::cpp_uno::shared::isSimpleType( pReturnTD ) )
227  {
228  // Return value
229  ++nr;
230  }
231 
232  for (int param = 0; nr < 4 && param < pMethodTD->nParams; ++param, ++nr)
233  {
234  typelib_TypeDescription * pParamTD = nullptr;
235 
236  TYPELIB_DANGER_GET( &pParamTD, pMethodTD->pParams[param].pTypeRef );
237  assert(pParamTD);
238 
239  if ( pParamTD->eTypeClass == typelib_TypeClass_FLOAT ||
240  pParamTD->eTypeClass == typelib_TypeClass_DOUBLE )
241  param_kind[nr] = REGPARAM_FLT;
242 
243  TYPELIB_DANGER_RELEASE( pParamTD );
244  }
245  (s++)->fn = code;
246  code = codeSnippet( code, param_kind, nFunctionOffset++, nVtableOffset );
247 
248  TYPELIB_DANGER_RELEASE( pReturnTD );
249  }
250  else
251  assert(false);
252 
253  TYPELIB_DANGER_RELEASE( pTD );
254  }
255  return code;
256 }
257 
259  unsigned char const *,
260  unsigned char const *)
261 {
262 }
263 
264 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
int n1
typelib_TypeClass cpp_vtable_call(sal_Int64 nOffsetAndIndex, void **pCallStack)
bool isSimpleType(typelib_TypeClass typeClass)
Determines whether a type is a "simple" type (VOID, BOOLEAN, BYTE, SHORT, UNSIGNED SHORT...
Definition: types.cxx:28
static std::size_t getBlockSize(sal_Int32 slotCount)
Calculate the size of a raw vtable block.
int n2
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
static Slot * initializeBlock(void *block, sal_Int32 slotCount, sal_Int32 vtableNumber, typelib_InterfaceTypeDescription *type)
Initialize a raw vtable block.
typelib_TypeClass __cdecl cpp_mediate(void **pCallStack, const sal_Int32 nFunctionIndex, const sal_Int32 nVtableOffset, sal_Int64 *const pRegisterReturn)
static Slot * mapBlockToVtable(void *block)
Given a pointer to a block, turn it into a vtable pointer.
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...
int i
char privateSnippetExecutor
struct _typelib_TypeDescription typelib_TypeDescription
Definition: msvc/except.hxx:52
static unsigned char * codeSnippet(unsigned char *code, RegParamKind param_kind[4], sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset)
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.
void * p
int const codeSnippetSize