1 //===----- ABI.h - ABI related declarations ---------------------*- 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 ABI related information about constructors, 11 /// destructors and thunks. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_BASIC_ABI_H 16 #define LLVM_CLANG_BASIC_ABI_H 17 18 #include "llvm/Support/DataTypes.h" 19 #include <cstring> 20 21 namespace clang { 22 23 /// C++ constructor types. 24 enum CXXCtorType { 25 Ctor_Complete, ///< Complete object ctor 26 Ctor_Base, ///< Base object ctor 27 Ctor_Comdat, ///< The COMDAT used for ctors 28 Ctor_CopyingClosure, ///< Copying closure variant of a ctor 29 Ctor_DefaultClosure, ///< Default closure variant of a ctor 30 }; 31 32 /// C++ destructor types. 33 enum CXXDtorType { 34 Dtor_Deleting, ///< Deleting dtor 35 Dtor_Complete, ///< Complete object dtor 36 Dtor_Base, ///< Base object dtor 37 Dtor_Comdat ///< The COMDAT used for dtors 38 }; 39 40 /// A return adjustment. 41 struct ReturnAdjustment { 42 /// The non-virtual adjustment from the derived object to its 43 /// nearest virtual base. 44 int64_t NonVirtual; 45 46 /// Holds the ABI-specific information about the virtual return 47 /// adjustment, if needed. 48 union VirtualAdjustment { 49 // Itanium ABI 50 struct { 51 /// The offset (in bytes), relative to the address point 52 /// of the virtual base class offset. 53 int64_t VBaseOffsetOffset; 54 } Itanium; 55 56 // Microsoft ABI 57 struct { 58 /// The offset (in bytes) of the vbptr, relative to the beginning 59 /// of the derived class. 60 uint32_t VBPtrOffset; 61 62 /// Index of the virtual base in the vbtable. 63 uint32_t VBIndex; 64 } Microsoft; 65 66 VirtualAdjustment() { 67 memset(this, 0, sizeof(*this)); 68 } 69 70 bool Equals(const VirtualAdjustment &Other) const { 71 return memcmp(this, &Other, sizeof(Other)) == 0; 72 } 73 74 bool isEmpty() const { 75 VirtualAdjustment Zero; 76 return Equals(Zero); 77 } 78 79 bool Less(const VirtualAdjustment &RHS) const { 80 return memcmp(this, &RHS, sizeof(RHS)) < 0; 81 } 82 } Virtual; 83 84 ReturnAdjustment() : NonVirtual(0) {} 85 86 bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); } 87 88 friend bool operator==(const ReturnAdjustment &LHS, 89 const ReturnAdjustment &RHS) { 90 return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual); 91 } 92 93 friend bool operator!=(const ReturnAdjustment &LHS, const ReturnAdjustment &RHS) { 94 return !(LHS == RHS); 95 } 96 97 friend bool operator<(const ReturnAdjustment &LHS, 98 const ReturnAdjustment &RHS) { 99 if (LHS.NonVirtual < RHS.NonVirtual) 100 return true; 101 102 return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual); 103 } 104 }; 105 106 /// A \c this pointer adjustment. 107 struct ThisAdjustment { 108 /// The non-virtual adjustment from the derived object to its 109 /// nearest virtual base. 110 int64_t NonVirtual; 111 112 /// Holds the ABI-specific information about the virtual this 113 /// adjustment, if needed. 114 union VirtualAdjustment { 115 // Itanium ABI 116 struct { 117 /// The offset (in bytes), relative to the address point, 118 /// of the virtual call offset. 119 int64_t VCallOffsetOffset; 120 } Itanium; 121 122 struct { 123 /// The offset of the vtordisp (in bytes), relative to the ECX. 124 int32_t VtordispOffset; 125 126 /// The offset of the vbptr of the derived class (in bytes), 127 /// relative to the ECX after vtordisp adjustment. 128 int32_t VBPtrOffset; 129 130 /// The offset (in bytes) of the vbase offset in the vbtable. 131 int32_t VBOffsetOffset; 132 } Microsoft; 133 134 VirtualAdjustment() { 135 memset(this, 0, sizeof(*this)); 136 } 137 138 bool Equals(const VirtualAdjustment &Other) const { 139 return memcmp(this, &Other, sizeof(Other)) == 0; 140 } 141 142 bool isEmpty() const { 143 VirtualAdjustment Zero; 144 return Equals(Zero); 145 } 146 147 bool Less(const VirtualAdjustment &RHS) const { 148 return memcmp(this, &RHS, sizeof(RHS)) < 0; 149 } 150 } Virtual; 151 152 ThisAdjustment() : NonVirtual(0) { } 153 154 bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); } 155 156 friend bool operator==(const ThisAdjustment &LHS, 157 const ThisAdjustment &RHS) { 158 return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual); 159 } 160 161 friend bool operator!=(const ThisAdjustment &LHS, const ThisAdjustment &RHS) { 162 return !(LHS == RHS); 163 } 164 165 friend bool operator<(const ThisAdjustment &LHS, 166 const ThisAdjustment &RHS) { 167 if (LHS.NonVirtual < RHS.NonVirtual) 168 return true; 169 170 return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual); 171 } 172 }; 173 174 class CXXMethodDecl; 175 176 /// The \c this pointer adjustment as well as an optional return 177 /// adjustment for a thunk. 178 struct ThunkInfo { 179 /// The \c this pointer adjustment. 180 ThisAdjustment This; 181 182 /// The return adjustment. 183 ReturnAdjustment Return; 184 185 /// Holds a pointer to the overridden method this thunk is for, 186 /// if needed by the ABI to distinguish different thunks with equal 187 /// adjustments. Otherwise, null. 188 /// CAUTION: In the unlikely event you need to sort ThunkInfos, consider using 189 /// an ABI-specific comparator. 190 const CXXMethodDecl *Method; 191 192 ThunkInfo() : Method(nullptr) { } 193 194 ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return, 195 const CXXMethodDecl *Method = nullptr) 196 : This(This), Return(Return), Method(Method) {} 197 198 friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) { 199 return LHS.This == RHS.This && LHS.Return == RHS.Return && 200 LHS.Method == RHS.Method; 201 } 202 203 bool isEmpty() const { 204 return This.isEmpty() && Return.isEmpty() && Method == nullptr; 205 } 206 }; 207 208 } // end namespace clang 209 210 #endif 211