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 25 /// A return adjustment. 26 struct ReturnAdjustment { 27 /// The non-virtual adjustment from the derived object to its 28 /// nearest virtual base. 29 int64_t NonVirtual; 30 31 /// Holds the ABI-specific information about the virtual return 32 /// adjustment, if needed. 33 union VirtualAdjustment { 34 // Itanium ABI 35 struct { 36 /// The offset (in bytes), relative to the address point 37 /// of the virtual base class offset. 38 int64_t VBaseOffsetOffset; 39 } Itanium; 40 41 // Microsoft ABI 42 struct { 43 /// The offset (in bytes) of the vbptr, relative to the beginning 44 /// of the derived class. 45 uint32_t VBPtrOffset; 46 47 /// Index of the virtual base in the vbtable. 48 uint32_t VBIndex; 49 } Microsoft; 50 51 VirtualAdjustment() { memset(this, 0, sizeof(*this)); } 52 53 bool Equals(const VirtualAdjustment &Other) const { 54 return memcmp(this, &Other, sizeof(Other)) == 0; 55 } 56 57 bool isEmpty() const { 58 VirtualAdjustment Zero; 59 return Equals(Zero); 60 } 61 62 bool Less(const VirtualAdjustment &RHS) const { 63 return memcmp(this, &RHS, sizeof(RHS)) < 0; 64 } 65 } Virtual; 66 67 ReturnAdjustment() : NonVirtual(0) {} 68 69 bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); } 70 71 friend bool operator==(const ReturnAdjustment &LHS, 72 const ReturnAdjustment &RHS) { 73 return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual); 74 } 75 76 friend bool operator!=(const ReturnAdjustment &LHS, 77 const ReturnAdjustment &RHS) { 78 return !(LHS == RHS); 79 } 80 81 friend bool operator<(const ReturnAdjustment &LHS, 82 const ReturnAdjustment &RHS) { 83 if (LHS.NonVirtual < RHS.NonVirtual) 84 return true; 85 86 return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual); 87 } 88 }; 89 90 /// A \c this pointer adjustment. 91 struct ThisAdjustment { 92 /// The non-virtual adjustment from the derived object to its 93 /// nearest virtual base. 94 int64_t NonVirtual; 95 96 /// Holds the ABI-specific information about the virtual this 97 /// adjustment, if needed. 98 union VirtualAdjustment { 99 // Itanium ABI 100 struct { 101 /// The offset (in bytes), relative to the address point, 102 /// of the virtual call offset. 103 int64_t VCallOffsetOffset; 104 } Itanium; 105 106 struct { 107 /// The offset of the vtordisp (in bytes), relative to the ECX. 108 int32_t VtordispOffset; 109 110 /// The offset of the vbptr of the derived class (in bytes), 111 /// relative to the ECX after vtordisp adjustment. 112 int32_t VBPtrOffset; 113 114 /// The offset (in bytes) of the vbase offset in the vbtable. 115 int32_t VBOffsetOffset; 116 } Microsoft; 117 118 VirtualAdjustment() { memset(this, 0, sizeof(*this)); } 119 120 bool Equals(const VirtualAdjustment &Other) const { 121 return memcmp(this, &Other, sizeof(Other)) == 0; 122 } 123 124 bool isEmpty() const { 125 VirtualAdjustment Zero; 126 return Equals(Zero); 127 } 128 129 bool Less(const VirtualAdjustment &RHS) const { 130 return memcmp(this, &RHS, sizeof(RHS)) < 0; 131 } 132 } Virtual; 133 134 ThisAdjustment() : NonVirtual(0) {} 135 136 bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); } 137 138 friend bool operator==(const ThisAdjustment &LHS, const ThisAdjustment &RHS) { 139 return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual); 140 } 141 142 friend bool operator!=(const ThisAdjustment &LHS, const ThisAdjustment &RHS) { 143 return !(LHS == RHS); 144 } 145 146 friend bool operator<(const ThisAdjustment &LHS, const ThisAdjustment &RHS) { 147 if (LHS.NonVirtual < RHS.NonVirtual) 148 return true; 149 150 return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual); 151 } 152 }; 153 154 /// The \c this pointer adjustment as well as an optional return 155 /// adjustment for a thunk. 156 struct ThunkInfo { 157 /// The \c this pointer adjustment. 158 ThisAdjustment This; 159 160 /// The return adjustment. 161 ReturnAdjustment Return; 162 163 /// Holds a pointer to the overridden method this thunk is for, 164 /// if needed by the ABI to distinguish different thunks with equal 165 /// adjustments. Otherwise, null. 166 /// CAUTION: In the unlikely event you need to sort ThunkInfos, consider using 167 /// an ABI-specific comparator. 168 const CXXMethodDecl *Method; 169 170 ThunkInfo() : Method(nullptr) {} 171 172 ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return, 173 const CXXMethodDecl *Method = nullptr) 174 : This(This), Return(Return), Method(Method) {} 175 176 friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) { 177 return LHS.This == RHS.This && LHS.Return == RHS.Return && 178 LHS.Method == RHS.Method; 179 } 180 181 bool isEmpty() const { 182 return This.isEmpty() && Return.isEmpty() && Method == nullptr; 183 } 184 }; 185 186 } // end namespace clang 187 188 #endif 189