tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / bridges / source / cpp_uno / msvc_win32_intel / cpp2uno.cxx
blob577c318c5767aae18b34ae1d04e1c67965ec321f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
23 #include <typeinfo>
25 #include <malloc.h>
27 #include <com/sun/star/uno/genfunc.hxx>
28 #include <sal/log.hxx>
29 #include <uno/data.h>
30 #include <typelib/typedescription.hxx>
32 #include "bridge.hxx"
33 #include "cppinterfaceproxy.hxx"
34 #include "types.hxx"
35 #include "vtablefactory.hxx"
37 #include <msvc/x86.hxx>
38 #include <msvc/cpp2uno.hxx>
40 using namespace ::com::sun::star;
42 namespace
45 /**
46 * is called on incoming vtable calls
47 * (called by asm snippets)
49 static __declspec(naked) void __cdecl cpp_vtable_call()
51 __asm
53 sub esp, 8 // space for immediate return type
54 push esp
55 push edx // vtable offset
56 push eax // function index
57 mov eax, esp
58 add eax, 20
59 push eax // original stack ptr
61 call cpp_mediate
62 add esp, 16
64 cmp eax, typelib_TypeClass_FLOAT
65 je Lfloat
66 cmp eax, typelib_TypeClass_DOUBLE
67 je Ldouble
68 cmp eax, typelib_TypeClass_HYPER
69 je Lhyper
70 cmp eax, typelib_TypeClass_UNSIGNED_HYPER
71 je Lhyper
72 // rest is eax
73 pop eax
74 add esp, 4
75 ret
76 Lhyper:
77 pop eax
78 pop edx
79 ret
80 Lfloat:
81 fld dword ptr [esp]
82 add esp, 8
83 ret
84 Ldouble:
85 fld qword ptr [esp]
86 add esp, 8
87 ret
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:
99 *p++ = 0xB8;
100 *reinterpret_cast< sal_Int32 * >(p) = functionIndex;
101 p += sizeof (sal_Int32);
102 // mov edx, vtableOffset:
103 *p++ = 0xBA;
104 *reinterpret_cast< sal_Int32 * >(p) = vtableOffset;
105 p += sizeof (sal_Int32);
106 // jmp rel32 cpp_vtable_call:
107 *p++ = 0xE9;
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(
126 sal_Int32 slotCount)
128 return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize;
131 namespace {
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:
135 struct ProxyRtti {};
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
139 // such data:
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));
148 sal_uInt32 n1 = 0;
149 sal_uInt32 n2 = 0;
150 sal_uInt32 n3 = 0xFFFFFFFF;
151 sal_uInt32 n4 = 0;
152 sal_uInt32 n5 = 0x40;
153 sal_uInt32 n6;
154 RttiBaseClassDescriptor(RttiClassHierarchyDescriptor const * chd):
155 n6(reinterpret_cast<sal_uInt32>(chd)) {}
158 struct alignas(4) RttiBaseClassArray {
159 sal_uInt32 n0;
160 sal_uInt32 n1 = 0;
161 RttiBaseClassArray(RttiBaseClassDescriptor const * bcd): n0(reinterpret_cast<sal_uInt32>(bcd))
165 struct alignas(4) RttiClassHierarchyDescriptor {
166 sal_uInt32 n0 = 0;
167 sal_uInt32 n1 = 0;
168 sal_uInt32 n2 = 1;
169 sal_uInt32 n3;
170 RttiClassHierarchyDescriptor(RttiBaseClassArray const * bca):
171 n3(reinterpret_cast<sal_uInt32>(bca)) {}
174 struct alignas(16) RttiCompleteObjectLocator {
175 sal_uInt32 n0 = 0;
176 sal_uInt32 n1 = 0;
177 sal_uInt32 n2 = 0;
178 sal_uInt32 n3 = reinterpret_cast<sal_uInt32>(&typeid(ProxyRtti));
179 sal_uInt32 n4;
180 RttiCompleteObjectLocator(RttiClassHierarchyDescriptor const * chd):
181 n4(reinterpret_cast<sal_uInt32>(chd)) {}
184 struct Rtti {
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 *)
201 static Rtti rtti;
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;
214 Slot * s = *slots;
215 for (sal_Int32 i = 0; i < functionCount; ++i) {
216 (s++)->fn = code;
217 code = codeSnippet(code, functionOffset++, vtableOffset);
219 return code;
222 void bridges::cpp_uno::shared::VtableFactory::flushCode(
223 unsigned char const *,
224 unsigned char const *)
228 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */