19258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org//===----- ABI.h - ABI related declarations ---------------------*- C++ -*-===//
29a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//
39a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//                     The LLVM Compiler Infrastructure
49a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//
59a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// This file is distributed under the University of Illinois Open Source
69a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// License. See LICENSE.TXT for details.
79a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//
89a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//===----------------------------------------------------------------------===//
99a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com///
109a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com/// \file
119a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com/// \brief Enums/classes describing ABI related information about constructors,
129a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com/// destructors and thunks.
139a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com///
149a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//===----------------------------------------------------------------------===//
159a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
169a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com#ifndef CLANG_BASIC_ABI_H
179a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com#define CLANG_BASIC_ABI_H
189a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
199a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com#include "llvm/Support/DataTypes.h"
209a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
219a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comnamespace clang {
229a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
239a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com/// \brief C++ constructor types.
249a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comenum CXXCtorType {
259a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    Ctor_Complete,          ///< Complete object ctor
269a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    Ctor_Base,              ///< Base object ctor
279a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    Ctor_CompleteAllocating ///< Complete object allocating ctor
289a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com};
299a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
309a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com/// \brief C++ destructor types.
319a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comenum CXXDtorType {
329a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    Dtor_Deleting, ///< Deleting dtor
339a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    Dtor_Complete, ///< Complete object dtor
349d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    Dtor_Base      ///< Base object dtor
359d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com};
369d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
379a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com/// \brief A return adjustment.
389d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comstruct ReturnAdjustment {
399d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  /// \brief The non-virtual adjustment from the derived object to its
409d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  /// nearest virtual base.
419a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  int64_t NonVirtual;
429d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
439d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  /// \brief Holds the ABI-specific information about the virtual return
449d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  /// adjustment, if needed.
459a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  union VirtualAdjustment {
469d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    // Itanium ABI
479d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    struct {
489d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com      /// \brief The offset (in bytes), relative to the address point
499a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com      /// of the virtual base class offset.
509a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com      int64_t VBaseOffsetOffset;
519a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    } Itanium;
529a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
539a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    // Microsoft ABI
549a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    struct {
559a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com      /// \brief The offset (in bytes) of the vbptr, relative to the beginning
569a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com      /// of the derived class.
579d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com      uint32_t VBPtrOffset;
589a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
599a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com      /// \brief Index of the virtual base in the vbtable.
609d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com      uint32_t VBIndex;
619a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    } Microsoft;
629d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
639a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    VirtualAdjustment() {
649d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com      memset(this, 0, sizeof(*this));
659a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    }
669d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
679a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    bool Equals(const VirtualAdjustment &Other) const {
689a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com      return memcmp(this, &Other, sizeof(Other)) == 0;
699d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com    }
709258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org
719258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org    bool isEmpty() const {
729258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org      VirtualAdjustment Zero;
739d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com      return Equals(Zero);
749258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org    }
759258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org
769258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org    bool Less(const VirtualAdjustment &RHS) const {
779d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com      return memcmp(this, &RHS, sizeof(RHS)) < 0;
789258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org    }
799258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  } Virtual;
809258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org
819d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  ReturnAdjustment() : NonVirtual(0) {}
829258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org
839258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
849258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org
859d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  friend bool operator==(const ReturnAdjustment &LHS,
869258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org                         const ReturnAdjustment &RHS) {
8740b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org    return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
8840b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  }
8940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org
9040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  friend bool operator!=(const ReturnAdjustment &LHS, const ReturnAdjustment &RHS) {
9140b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org    return !(LHS == RHS);
9240b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  }
9340b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org
9440b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  friend bool operator<(const ReturnAdjustment &LHS,
9540b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org                        const ReturnAdjustment &RHS) {
9640b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org    if (LHS.NonVirtual < RHS.NonVirtual)
9740b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      return true;
9840b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org
9940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org    return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
10040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  }
10140b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org};
10240b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org
10340b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org/// \brief A \c this pointer adjustment.
10440b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.orgstruct ThisAdjustment {
10540b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  /// \brief The non-virtual adjustment from the derived object to its
10640b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  /// nearest virtual base.
10740b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  int64_t NonVirtual;
10840b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org
10940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  /// \brief Holds the ABI-specific information about the virtual this
11040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  /// adjustment, if needed.
11140b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org  union VirtualAdjustment {
11240b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org    // Itanium ABI
11340b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org    struct {
11440b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      /// \brief The offset (in bytes), relative to the address point,
11540b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      /// of the virtual call offset.
11640b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      int64_t VCallOffsetOffset;
11740b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org    } Itanium;
11840b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org
11940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org    struct {
12040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      /// \brief The offset of the vtordisp (in bytes), relative to the ECX.
12140b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      int32_t VtordispOffset;
122
123      /// \brief The offset of the vbptr of the derived class (in bytes),
124      /// relative to the ECX after vtordisp adjustment.
125      int32_t VBPtrOffset;
126
127      /// \brief The offset (in bytes) of the vbase offset in the vbtable.
128      int32_t VBOffsetOffset;
129    } Microsoft;
130
131    VirtualAdjustment() {
132      memset(this, 0, sizeof(*this));
133    }
134
135    bool Equals(const VirtualAdjustment &Other) const {
136      return memcmp(this, &Other, sizeof(Other)) == 0;
137    }
138
139    bool isEmpty() const {
140      VirtualAdjustment Zero;
141      return Equals(Zero);
142    }
143
144    bool Less(const VirtualAdjustment &RHS) const {
145      return memcmp(this, &RHS, sizeof(RHS)) < 0;
146    }
147  } Virtual;
148
149  ThisAdjustment() : NonVirtual(0) { }
150
151  bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
152
153  friend bool operator==(const ThisAdjustment &LHS,
154                         const ThisAdjustment &RHS) {
155    return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
156  }
157
158  friend bool operator!=(const ThisAdjustment &LHS, const ThisAdjustment &RHS) {
159    return !(LHS == RHS);
160  }
161
162  friend bool operator<(const ThisAdjustment &LHS,
163                        const ThisAdjustment &RHS) {
164    if (LHS.NonVirtual < RHS.NonVirtual)
165      return true;
166
167    return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
168  }
169};
170
171class CXXMethodDecl;
172
173/// \brief The \c this pointer adjustment as well as an optional return
174/// adjustment for a thunk.
175struct ThunkInfo {
176  /// \brief The \c this pointer adjustment.
177  ThisAdjustment This;
178
179  /// \brief The return adjustment.
180  ReturnAdjustment Return;
181
182  /// \brief Holds a pointer to the overridden method this thunk is for,
183  /// if needed by the ABI to distinguish different thunks with equal
184  /// adjustments. Otherwise, null.
185  /// CAUTION: In the unlikely event you need to sort ThunkInfos, consider using
186  /// an ABI-specific comparator.
187  const CXXMethodDecl *Method;
188
189  ThunkInfo() : Method(nullptr) { }
190
191  ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return,
192            const CXXMethodDecl *Method = nullptr)
193      : This(This), Return(Return), Method(Method) {}
194
195  friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) {
196    return LHS.This == RHS.This && LHS.Return == RHS.Return &&
197           LHS.Method == RHS.Method;
198  }
199
200  bool isEmpty() const {
201    return This.isEmpty() && Return.isEmpty() && Method == nullptr;
202  }
203};
204
205} // end namespace clang
206
207#endif // CLANG_BASIC_ABI_H
208