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
37using namespace ::com::sun::star;
38
39extern "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
46int const codeSnippetSize = 48;
47
48namespace {
49
50typedef enum { REGPARAM_INT, REGPARAM_FLT } RegParamKind;
51
52}
53
54extern "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
62static 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: */
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 * p
int n2
int n1
struct _typelib_TypeDescription typelib_TypeDescription
Definition: msvc/except.hxx:52
typelib_TypeClass __cdecl cpp_mediate(void **pCallStack, const sal_Int32 nFunctionIndex, const sal_Int32 nVtableOffset, sal_Int64 *const pRegisterReturn)
typelib_TypeClass cpp_vtable_call(sal_Int64 nOffsetAndIndex, void **pCallStack)
int const codeSnippetSize
static unsigned char * codeSnippet(unsigned char *code, RegParamKind param_kind[4], sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset)
char privateSnippetExecutor
bool isSimpleType(typelib_TypeClass typeClass)
Determines whether a type is a "simple" type (VOID, BOOLEAN, BYTE, SHORT, UNSIGNED SHORT,...
Definition: types.cxx:28
int i
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
sal_Unicode code
ResultType type