xref: /freebsd/contrib/llvm-project/clang/include/clang/Basic/Thunk.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===----- Thunk.h - Declarations related to VTable Thunks ------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// Enums/classes describing THUNK related information about constructors,
11 /// destructors and thunks.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_BASIC_THUNK_H
16 #define LLVM_CLANG_BASIC_THUNK_H
17 
18 #include <cstdint>
19 #include <cstring>
20 
21 namespace clang {
22 
23 class CXXMethodDecl;
24 class Type;
25 
26 /// A return adjustment.
27 struct ReturnAdjustment {
28   /// The non-virtual adjustment from the derived object to its
29   /// nearest virtual base.
30   int64_t NonVirtual = 0;
31 
32   /// Holds the ABI-specific information about the virtual return
33   /// adjustment, if needed.
34   union VirtualAdjustment {
35     // Itanium ABI
36     struct {
37       /// The offset (in bytes), relative to the address point
38       /// of the virtual base class offset.
39       int64_t VBaseOffsetOffset;
40     } Itanium;
41 
42     // Microsoft ABI
43     struct {
44       /// The offset (in bytes) of the vbptr, relative to the beginning
45       /// of the derived class.
46       uint32_t VBPtrOffset;
47 
48       /// Index of the virtual base in the vbtable.
49       uint32_t VBIndex;
50     } Microsoft;
51 
VirtualAdjustment()52     VirtualAdjustment() { memset(this, 0, sizeof(*this)); }
53 
Equals(const VirtualAdjustment & Other)54     bool Equals(const VirtualAdjustment &Other) const {
55       return memcmp(this, &Other, sizeof(Other)) == 0;
56     }
57 
isEmpty()58     bool isEmpty() const {
59       VirtualAdjustment Zero;
60       return Equals(Zero);
61     }
62 
Less(const VirtualAdjustment & RHS)63     bool Less(const VirtualAdjustment &RHS) const {
64       return memcmp(this, &RHS, sizeof(RHS)) < 0;
65     }
66   } Virtual;
67 
68   ReturnAdjustment() = default;
69 
isEmptyReturnAdjustment70   bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
71 
72   friend bool operator==(const ReturnAdjustment &LHS,
73                          const ReturnAdjustment &RHS) {
74     return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
75   }
76 
77   friend bool operator!=(const ReturnAdjustment &LHS,
78                          const ReturnAdjustment &RHS) {
79     return !(LHS == RHS);
80   }
81 
82   friend bool operator<(const ReturnAdjustment &LHS,
83                         const ReturnAdjustment &RHS) {
84     if (LHS.NonVirtual < RHS.NonVirtual)
85       return true;
86 
87     return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
88   }
89 };
90 
91 /// A \c this pointer adjustment.
92 struct ThisAdjustment {
93   /// The non-virtual adjustment from the derived object to its
94   /// nearest virtual base.
95   int64_t NonVirtual = 0;
96 
97   /// Holds the ABI-specific information about the virtual this
98   /// adjustment, if needed.
99   union VirtualAdjustment {
100     // Itanium ABI
101     struct {
102       /// The offset (in bytes), relative to the address point,
103       /// of the virtual call offset.
104       int64_t VCallOffsetOffset;
105     } Itanium;
106 
107     struct {
108       /// The offset of the vtordisp (in bytes), relative to the ECX.
109       int32_t VtordispOffset;
110 
111       /// The offset of the vbptr of the derived class (in bytes),
112       /// relative to the ECX after vtordisp adjustment.
113       int32_t VBPtrOffset;
114 
115       /// The offset (in bytes) of the vbase offset in the vbtable.
116       int32_t VBOffsetOffset;
117     } Microsoft;
118 
VirtualAdjustment()119     VirtualAdjustment() { memset(this, 0, sizeof(*this)); }
120 
Equals(const VirtualAdjustment & Other)121     bool Equals(const VirtualAdjustment &Other) const {
122       return memcmp(this, &Other, sizeof(Other)) == 0;
123     }
124 
isEmpty()125     bool isEmpty() const {
126       VirtualAdjustment Zero;
127       return Equals(Zero);
128     }
129 
Less(const VirtualAdjustment & RHS)130     bool Less(const VirtualAdjustment &RHS) const {
131       return memcmp(this, &RHS, sizeof(RHS)) < 0;
132     }
133   } Virtual;
134 
135   ThisAdjustment() = default;
136 
isEmptyThisAdjustment137   bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
138 
139   friend bool operator==(const ThisAdjustment &LHS, const ThisAdjustment &RHS) {
140     return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
141   }
142 
143   friend bool operator!=(const ThisAdjustment &LHS, const ThisAdjustment &RHS) {
144     return !(LHS == RHS);
145   }
146 
147   friend bool operator<(const ThisAdjustment &LHS, const ThisAdjustment &RHS) {
148     if (LHS.NonVirtual < RHS.NonVirtual)
149       return true;
150 
151     return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
152   }
153 };
154 
155 /// The \c this pointer adjustment as well as an optional return
156 /// adjustment for a thunk.
157 struct ThunkInfo {
158   /// The \c this pointer adjustment.
159   ThisAdjustment This;
160 
161   /// The return adjustment.
162   ReturnAdjustment Return;
163 
164   /// Holds a pointer to the overridden method this thunk is for,
165   /// if needed by the ABI to distinguish different thunks with equal
166   /// adjustments.
167   /// In the Itanium ABI, this field can hold the method that created the
168   /// vtable entry for this thunk.
169   /// Otherwise, null.
170   /// CAUTION: In the unlikely event you need to sort ThunkInfos, consider using
171   /// an ABI-specific comparator.
172   const CXXMethodDecl *Method;
173   const Type *ThisType;
174 
ThunkInfoThunkInfo175   ThunkInfo() : Method(nullptr), ThisType(nullptr) {}
176 
177   ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return,
178             const Type *ThisT, const CXXMethodDecl *Method = nullptr)
ThisThunkInfo179       : This(This), Return(Return), Method(Method), ThisType(ThisT) {}
180 
181   friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) {
182     return LHS.This == RHS.This && LHS.Return == RHS.Return &&
183            LHS.Method == RHS.Method && LHS.ThisType == RHS.ThisType;
184   }
185 
isEmptyThunkInfo186   bool isEmpty() const {
187     return This.isEmpty() && Return.isEmpty() && Method == nullptr;
188   }
189 };
190 
191 } // end namespace clang
192 
193 #endif
194