1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <sal/config.h>
27 #include <com/sun/star/uno/genfunc.hxx>
28 #include <sal/log.hxx>
30 #include <typelib/typedescription.hxx>
33 #include "cppinterfaceproxy.hxx"
35 #include "vtablefactory.hxx"
37 #include <msvc/x86.hxx>
38 #include <msvc/cpp2uno.hxx>
40 using namespace ::com::sun::star
;
46 * is called on incoming vtable calls
47 * (called by asm snippets)
49 static __declspec(naked
) void __cdecl
cpp_vtable_call()
53 sub esp
, 8 // space for immediate return type
55 push edx
// vtable offset
56 push eax
// function index
59 push eax
// original stack ptr
64 cmp eax
, typelib_TypeClass_FLOAT
66 cmp eax
, typelib_TypeClass_DOUBLE
68 cmp eax
, typelib_TypeClass_HYPER
70 cmp eax
, typelib_TypeClass_UNSIGNED_HYPER
91 int const codeSnippetSize
= 16;
93 unsigned char * codeSnippet(
94 unsigned char * code
, sal_Int32 functionIndex
, sal_Int32 vtableOffset
)
96 unsigned char * p
= code
;
97 static_assert(sizeof (sal_Int32
) == 4, "boo");
98 // mov eax, functionIndex:
100 *reinterpret_cast< sal_Int32
* >(p
) = functionIndex
;
101 p
+= sizeof (sal_Int32
);
102 // mov edx, vtableOffset:
104 *reinterpret_cast< sal_Int32
* >(p
) = vtableOffset
;
105 p
+= sizeof (sal_Int32
);
106 // jmp rel32 cpp_vtable_call:
108 *reinterpret_cast< sal_Int32
* >(p
)
109 = ((unsigned char *) cpp_vtable_call
) - p
- sizeof (sal_Int32
);
110 p
+= sizeof (sal_Int32
);
111 assert(p
- code
<= codeSnippetSize
);
112 return code
+ codeSnippetSize
;
117 struct bridges::cpp_uno::shared::VtableFactory::Slot
{ void * fn
; };
119 bridges::cpp_uno::shared::VtableFactory::Slot
*
120 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block
)
122 return static_cast< Slot
* >(block
) + 1;
125 std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize(
128 return (slotCount
+ 1) * sizeof (Slot
) + slotCount
* codeSnippetSize
;
133 // Some dummy type whose RTTI is used in the synthesized proxy vtables to make uses of dynamic_cast
134 // on such proxy objects not crash:
137 // The following vtable RTTI data is based on how the code at
138 // <https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/MicrosoftCXXABI.cpp> computes
141 struct RttiClassHierarchyDescriptor
;
143 #pragma warning (push)
144 #pragma warning (disable: 4324) // "structure was padded due to alignment specifier"
146 struct alignas(16) RttiBaseClassDescriptor
{
147 sal_uInt32 n0
= reinterpret_cast<sal_uInt32
>(&typeid(ProxyRtti
));
150 sal_uInt32 n3
= 0xFFFFFFFF;
152 sal_uInt32 n5
= 0x40;
154 RttiBaseClassDescriptor(RttiClassHierarchyDescriptor
const * chd
):
155 n6(reinterpret_cast<sal_uInt32
>(chd
)) {}
158 struct alignas(4) RttiBaseClassArray
{
161 RttiBaseClassArray(RttiBaseClassDescriptor
const * bcd
): n0(reinterpret_cast<sal_uInt32
>(bcd
))
165 struct alignas(4) RttiClassHierarchyDescriptor
{
170 RttiClassHierarchyDescriptor(RttiBaseClassArray
const * bca
):
171 n3(reinterpret_cast<sal_uInt32
>(bca
)) {}
174 struct alignas(16) RttiCompleteObjectLocator
{
178 sal_uInt32 n3
= reinterpret_cast<sal_uInt32
>(&typeid(ProxyRtti
));
180 RttiCompleteObjectLocator(RttiClassHierarchyDescriptor
const * chd
):
181 n4(reinterpret_cast<sal_uInt32
>(chd
)) {}
185 RttiBaseClassDescriptor bcd
;
186 RttiBaseClassArray bca
;
187 RttiClassHierarchyDescriptor chd
;
188 RttiCompleteObjectLocator col
;
189 Rtti(): bcd(&chd
), bca(&bcd
), chd(&bca
), col(&chd
) {}
192 #pragma warning (pop)
196 bridges::cpp_uno::shared::VtableFactory::Slot
*
197 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
198 void * block
, sal_Int32 slotCount
, sal_Int32
,
199 typelib_InterfaceTypeDescription
*)
203 Slot
* slots
= mapBlockToVtable(block
);
204 slots
[-1].fn
= &rtti
.col
;
205 return slots
+ slotCount
;
208 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
209 Slot
** slots
, unsigned char * code
,
210 typelib_InterfaceTypeDescription
const *, sal_Int32 functionOffset
,
211 sal_Int32 functionCount
, sal_Int32 vtableOffset
)
213 (*slots
) -= functionCount
;
215 for (sal_Int32 i
= 0; i
< functionCount
; ++i
) {
217 code
= codeSnippet(code
, functionOffset
++, vtableOffset
);
222 void bridges::cpp_uno::shared::VtableFactory::flushCode(
223 unsigned char const *,
224 unsigned char const *)
228 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */