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