LibreOffice Module bridges (master)  1
gcc3_linux_x86-64/callvirtualmethod.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 #include <sal/config.h>
21 
22 #include <cstring>
23 
24 #include <cppu/macros.hxx>
25 #include <sal/types.h>
26 #include <typelib/typeclass.h>
27 #include <typelib/typedescription.h>
28 
29 #include "abi.hxx"
30 #include "callvirtualmethod.hxx"
31 
32 // The call instruction within the asm block of callVirtualMethod may throw
33 // exceptions. At least GCC 4.7.0 with -O0 would create (unnecessary)
34 // .gcc_exception_table call-site table entries around all other calls in this
35 // function that can throw, leading to std::terminate if the asm call throws an
36 // exception and the unwinding C++ personality routine finds the unexpected hole
37 // in the .gcc_exception_table. Therefore, make sure this function explicitly
38 // only calls nothrow-functions (so GCC 4.7.0 with -O0 happens to not create a
39 // .gcc_exception_table section at all for this function). For some reason,
40 // this also needs to be in a source file of its own.
41 //
42 // Also, this file should be compiled with -fnon-call-exceptions, and ideally
43 // there would be a way to tell the compiler that the asm block contains calls
44 // to functions that can potentially throw; see the mail thread starting at
45 // <http://gcc.gnu.org/ml/gcc/2012-03/msg00454.html> "C++: Letting compiler know
46 // asm block can call function that can throw?"
47 
49  void * pThis, sal_uInt32 nVtableIndex, void * pRegisterReturn,
50  typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn,
51  sal_uInt64 *pStack, sal_uInt32 nStack, sal_uInt64 *pGPR, double * pFPR)
52 {
53  // Work around Clang -fsanitize=address "inline assembly requires more
54  // registers than available" error:
55  struct Data {
56  sal_uInt64 pMethod;
57  sal_uInt64 * pStack;
58  sal_uInt32 nStack;
59  sal_uInt64 * pGPR;
60  double * pFPR;
61  // Return values:
62  sal_uInt64 rax;
63  sal_uInt64 rdx;
64  double xmm0;
65  double xmm1;
66  } data;
67  data.pStack = pStack;
68  data.nStack = nStack;
69  data.pGPR = pGPR;
70  data.pFPR = pFPR;
71 
72  // Get pointer to method
73  sal_uInt64 pMethod = *static_cast<sal_uInt64 *>(pThis);
74  pMethod += 8 * nVtableIndex;
75  data.pMethod = *reinterpret_cast<sal_uInt64 *>(pMethod);
76 
77  asm volatile (
78  // Push arguments to stack
79  "movq %%rsp, %%r12\n\t"
80  "movl 16%0, %%ecx\n\t"
81  "jrcxz .Lpushed\n\t"
82  "xor %%rax, %%rax\n\t"
83  "leaq (%%rax, %%rcx, 8), %%rax\n\t"
84  "subq %%rax, %%rsp\n\t"
85  "andq $-9, %%rsp\n\t" // 16-bytes aligned
86  "movq 8%0, %%rsi\n\t"
87  "\n.Lpush:\n\t"
88  "decq %%rcx\n\t"
89  "movq (%%rsi, %%rcx, 8), %%rax\n\t"
90  "movq %%rax, (%%rsp, %%rcx, 8)\n\t"
91  "jnz .Lpush\n\t"
92  "\n.Lpushed:\n\t"
93 
94  // Fill the xmm registers
95  "movq 32%0, %%rax\n\t"
96 
97  "movsd (%%rax), %%xmm0\n\t"
98  "movsd 8(%%rax), %%xmm1\n\t"
99  "movsd 16(%%rax), %%xmm2\n\t"
100  "movsd 24(%%rax), %%xmm3\n\t"
101  "movsd 32(%%rax), %%xmm4\n\t"
102  "movsd 40(%%rax), %%xmm5\n\t"
103  "movsd 48(%%rax), %%xmm6\n\t"
104  "movsd 56(%%rax), %%xmm7\n\t"
105 
106  // Fill the general purpose registers
107  "movq 24%0, %%rax\n\t"
108 
109  "movq (%%rax), %%rdi\n\t"
110  "movq 8(%%rax), %%rsi\n\t"
111  "movq 16(%%rax), %%rdx\n\t"
112  "movq 24(%%rax), %%rcx\n\t"
113  "movq 32(%%rax), %%r8\n\t"
114  "movq 40(%%rax), %%r9\n\t"
115 
116  // Perform the call
117  "movq 0%0, %%r11\n\t"
118  "call *%%r11\n\t"
119 
120  // Fill the return values
121  "movq %%rax, 40%0\n\t"
122  "movq %%rdx, 48%0\n\t"
123  "movsd %%xmm0, 56%0\n\t"
124  "movsd %%xmm1, 64%0\n\t"
125 
126  // Reset %rsp
127  "movq %%r12, %%rsp\n\t"
128  :: "o" (data)
129  : "rax", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12",
130  "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
131  "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
132  "memory"
133  );
134 
135  switch (pReturnTypeRef->eTypeClass)
136  {
137  case typelib_TypeClass_HYPER:
138  case typelib_TypeClass_UNSIGNED_HYPER:
139  *static_cast<sal_uInt64 *>( pRegisterReturn ) = data.rax;
140  break;
141  case typelib_TypeClass_LONG:
142  case typelib_TypeClass_UNSIGNED_LONG:
143  case typelib_TypeClass_ENUM:
144  *static_cast<sal_uInt32 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt32*>( &data.rax );
145  break;
146  case typelib_TypeClass_CHAR:
147  case typelib_TypeClass_SHORT:
148  case typelib_TypeClass_UNSIGNED_SHORT:
149  *static_cast<sal_uInt16 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt16*>( &data.rax );
150  break;
151  case typelib_TypeClass_BOOLEAN:
152  case typelib_TypeClass_BYTE:
153  *static_cast<sal_uInt8 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt8*>( &data.rax );
154  break;
155  case typelib_TypeClass_FLOAT:
156  case typelib_TypeClass_DOUBLE:
157  *static_cast<double *>( pRegisterReturn ) = data.xmm0;
158  break;
159  default:
160  {
161  sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize;
162  if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0)
163  {
164  sal_uInt64 longs[2];
165  longs[0] = data.rax;
166  longs[1] = data.rdx;
167 
168  double doubles[2];
169  doubles[0] = data.xmm0;
170  doubles[1] = data.xmm1;
171  x86_64::fill_struct( pReturnTypeRef, &longs[0], &doubles[0], pRegisterReturn);
172  }
173  break;
174  }
175  }
176 }
177 
178 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void fill_struct(typelib_TypeDescriptionReference *pTypeRef, const sal_uInt64 *pGPR, const double *pSSE, void *pStruct) noexcept
void callVirtualMethod(void *pAdjustedThisPtr, sal_Int32 nVtableIndex, void *pRegisterReturn, typelib_TypeDescription *pReturnTypeDescr, bool bSimpleReturn, sal_Int32 *pStackLongs, sal_Int32 nStackLongs)
exports com.sun.star.chart2. data
unsigned char sal_uInt8
if(aStr!=aBuf) UpdateName_Impl(m_xFollowLb.get()