diff --git a/clang/include/clang/AST/VTableBuilder.h b/clang/include/clang/AST/VTableBuilder.h index 241dd13f903e56..e451f3f861b792 100644 --- a/clang/include/clang/AST/VTableBuilder.h +++ b/clang/include/clang/AST/VTableBuilder.h @@ -18,6 +18,7 @@ #include "clang/AST/GlobalDecl.h" #include "clang/AST/RecordLayout.h" #include "clang/Basic/ABI.h" +#include "clang/Basic/Thunk.h" #include "llvm/ADT/DenseMap.h" #include #include diff --git a/clang/include/clang/Basic/ABI.h b/clang/include/clang/Basic/ABI.h index 2401ffa20494e9..231bad799a42cb 100644 --- a/clang/include/clang/Basic/ABI.h +++ b/clang/include/clang/Basic/ABI.h @@ -37,174 +37,6 @@ enum CXXDtorType { Dtor_Comdat ///< The COMDAT used for dtors }; -/// A return adjustment. -struct ReturnAdjustment { - /// The non-virtual adjustment from the derived object to its - /// nearest virtual base. - int64_t NonVirtual; - - /// Holds the ABI-specific information about the virtual return - /// adjustment, if needed. - union VirtualAdjustment { - // Itanium ABI - struct { - /// The offset (in bytes), relative to the address point - /// of the virtual base class offset. - int64_t VBaseOffsetOffset; - } Itanium; - - // Microsoft ABI - struct { - /// The offset (in bytes) of the vbptr, relative to the beginning - /// of the derived class. - uint32_t VBPtrOffset; - - /// Index of the virtual base in the vbtable. - uint32_t VBIndex; - } Microsoft; - - VirtualAdjustment() { - memset(this, 0, sizeof(*this)); - } - - bool Equals(const VirtualAdjustment &Other) const { - return memcmp(this, &Other, sizeof(Other)) == 0; - } - - bool isEmpty() const { - VirtualAdjustment Zero; - return Equals(Zero); - } - - bool Less(const VirtualAdjustment &RHS) const { - return memcmp(this, &RHS, sizeof(RHS)) < 0; - } - } Virtual; - - ReturnAdjustment() : NonVirtual(0) {} - - bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); } - - friend bool operator==(const ReturnAdjustment &LHS, - const ReturnAdjustment &RHS) { - return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual); - } - - friend bool operator!=(const ReturnAdjustment &LHS, const ReturnAdjustment &RHS) { - return !(LHS == RHS); - } - - friend bool operator<(const ReturnAdjustment &LHS, - const ReturnAdjustment &RHS) { - if (LHS.NonVirtual < RHS.NonVirtual) - return true; - - return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual); - } -}; - -/// A \c this pointer adjustment. -struct ThisAdjustment { - /// The non-virtual adjustment from the derived object to its - /// nearest virtual base. - int64_t NonVirtual; - - /// Holds the ABI-specific information about the virtual this - /// adjustment, if needed. - union VirtualAdjustment { - // Itanium ABI - struct { - /// The offset (in bytes), relative to the address point, - /// of the virtual call offset. - int64_t VCallOffsetOffset; - } Itanium; - - struct { - /// The offset of the vtordisp (in bytes), relative to the ECX. - int32_t VtordispOffset; - - /// The offset of the vbptr of the derived class (in bytes), - /// relative to the ECX after vtordisp adjustment. - int32_t VBPtrOffset; - - /// The offset (in bytes) of the vbase offset in the vbtable. - int32_t VBOffsetOffset; - } Microsoft; - - VirtualAdjustment() { - memset(this, 0, sizeof(*this)); - } - - bool Equals(const VirtualAdjustment &Other) const { - return memcmp(this, &Other, sizeof(Other)) == 0; - } - - bool isEmpty() const { - VirtualAdjustment Zero; - return Equals(Zero); - } - - bool Less(const VirtualAdjustment &RHS) const { - return memcmp(this, &RHS, sizeof(RHS)) < 0; - } - } Virtual; - - ThisAdjustment() : NonVirtual(0) { } - - bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); } - - friend bool operator==(const ThisAdjustment &LHS, - const ThisAdjustment &RHS) { - return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual); - } - - friend bool operator!=(const ThisAdjustment &LHS, const ThisAdjustment &RHS) { - return !(LHS == RHS); - } - - friend bool operator<(const ThisAdjustment &LHS, - const ThisAdjustment &RHS) { - if (LHS.NonVirtual < RHS.NonVirtual) - return true; - - return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual); - } -}; - -class CXXMethodDecl; - -/// The \c this pointer adjustment as well as an optional return -/// adjustment for a thunk. -struct ThunkInfo { - /// The \c this pointer adjustment. - ThisAdjustment This; - - /// The return adjustment. - ReturnAdjustment Return; - - /// Holds a pointer to the overridden method this thunk is for, - /// if needed by the ABI to distinguish different thunks with equal - /// adjustments. Otherwise, null. - /// CAUTION: In the unlikely event you need to sort ThunkInfos, consider using - /// an ABI-specific comparator. - const CXXMethodDecl *Method; - - ThunkInfo() : Method(nullptr) { } - - ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return, - const CXXMethodDecl *Method = nullptr) - : This(This), Return(Return), Method(Method) {} - - friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) { - return LHS.This == RHS.This && LHS.Return == RHS.Return && - LHS.Method == RHS.Method; - } - - bool isEmpty() const { - return This.isEmpty() && Return.isEmpty() && Method == nullptr; - } -}; - } // end namespace clang #endif diff --git a/clang/include/clang/Basic/Thunk.h b/clang/include/clang/Basic/Thunk.h new file mode 100644 index 00000000000000..7f3c4b24ec6d31 --- /dev/null +++ b/clang/include/clang/Basic/Thunk.h @@ -0,0 +1,185 @@ +//===----- Thunk.h - Declarations related to VTable Thunks ------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Enums/classes describing THUNK related information about constructors, +/// destructors and thunks. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_THUNK_H +#define LLVM_CLANG_BASIC_THUNK_H + +#include "clang/AST/GlobalDecl.h" + +namespace clang { + +/// A return adjustment. +struct ReturnAdjustment { + /// The non-virtual adjustment from the derived object to its + /// nearest virtual base. + int64_t NonVirtual; + + /// Holds the ABI-specific information about the virtual return + /// adjustment, if needed. + union VirtualAdjustment { + // Itanium ABI + struct { + /// The offset (in bytes), relative to the address point + /// of the virtual base class offset. + int64_t VBaseOffsetOffset; + } Itanium; + + // Microsoft ABI + struct { + /// The offset (in bytes) of the vbptr, relative to the beginning + /// of the derived class. + uint32_t VBPtrOffset; + + /// Index of the virtual base in the vbtable. + uint32_t VBIndex; + } Microsoft; + + VirtualAdjustment() { memset(this, 0, sizeof(*this)); } + + bool Equals(const VirtualAdjustment &Other) const { + return memcmp(this, &Other, sizeof(Other)) == 0; + } + + bool isEmpty() const { + VirtualAdjustment Zero; + return Equals(Zero); + } + + bool Less(const VirtualAdjustment &RHS) const { + return memcmp(this, &RHS, sizeof(RHS)) < 0; + } + } Virtual; + + ReturnAdjustment() : NonVirtual(0) {} + + bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); } + + friend bool operator==(const ReturnAdjustment &LHS, + const ReturnAdjustment &RHS) { + return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual); + } + + friend bool operator!=(const ReturnAdjustment &LHS, + const ReturnAdjustment &RHS) { + return !(LHS == RHS); + } + + friend bool operator<(const ReturnAdjustment &LHS, + const ReturnAdjustment &RHS) { + if (LHS.NonVirtual < RHS.NonVirtual) + return true; + + return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual); + } +}; + +/// A \c this pointer adjustment. +struct ThisAdjustment { + /// The non-virtual adjustment from the derived object to its + /// nearest virtual base. + int64_t NonVirtual; + + /// Holds the ABI-specific information about the virtual this + /// adjustment, if needed. + union VirtualAdjustment { + // Itanium ABI + struct { + /// The offset (in bytes), relative to the address point, + /// of the virtual call offset. + int64_t VCallOffsetOffset; + } Itanium; + + struct { + /// The offset of the vtordisp (in bytes), relative to the ECX. + int32_t VtordispOffset; + + /// The offset of the vbptr of the derived class (in bytes), + /// relative to the ECX after vtordisp adjustment. + int32_t VBPtrOffset; + + /// The offset (in bytes) of the vbase offset in the vbtable. + int32_t VBOffsetOffset; + } Microsoft; + + VirtualAdjustment() { memset(this, 0, sizeof(*this)); } + + bool Equals(const VirtualAdjustment &Other) const { + return memcmp(this, &Other, sizeof(Other)) == 0; + } + + bool isEmpty() const { + VirtualAdjustment Zero; + return Equals(Zero); + } + + bool Less(const VirtualAdjustment &RHS) const { + return memcmp(this, &RHS, sizeof(RHS)) < 0; + } + } Virtual; + + ThisAdjustment() : NonVirtual(0) {} + + bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); } + + friend bool operator==(const ThisAdjustment &LHS, const ThisAdjustment &RHS) { + return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual); + } + + friend bool operator!=(const ThisAdjustment &LHS, const ThisAdjustment &RHS) { + return !(LHS == RHS); + } + + friend bool operator<(const ThisAdjustment &LHS, const ThisAdjustment &RHS) { + if (LHS.NonVirtual < RHS.NonVirtual) + return true; + + return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual); + } +}; + +/// The \c this pointer adjustment as well as an optional return +/// adjustment for a thunk. +struct ThunkInfo { + /// The \c this pointer adjustment. + ThisAdjustment This; + + /// The return adjustment. + ReturnAdjustment Return; + + /// Holds a pointer to the overridden method this thunk is for, + /// if needed by the ABI to distinguish different thunks with equal + /// adjustments. Otherwise, null. + /// CAUTION: In the unlikely event you need to sort ThunkInfos, consider using + /// an ABI-specific comparator. + const CXXMethodDecl *Method; + + ThunkInfo() : Method(nullptr) {} + + ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return, + const CXXMethodDecl *Method = nullptr) + : This(This), Return(Return), Method(Method) {} + + friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) { + return LHS.This == RHS.This && LHS.Return == RHS.Return && + LHS.Method == RHS.Method; + } + + bool isEmpty() const { + return This.isEmpty() && Return.isEmpty() && Method == nullptr; + } +}; + +} // end namespace clang + +#endif diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 79fec683b7019d..7420103213db2b 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -14,7 +14,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/Mangle.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" @@ -23,14 +22,16 @@ #include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" -#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/Mangle.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/ABI.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Basic/Thunk.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h"