reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
  249
  250
  251
  252
  253
  254
  255
  256
  257
  258
  259
  260
  261
  262
  263
  264
  265
  266
  267
  268
  269
  270
  271
  272
  273
  274
  275
  276
  277
  278
  279
  280
  281
  282
  283
  284
  285
  286
  287
  288
  289
  290
  291
  292
  293
  294
  295
  296
  297
  298
  299
  300
  301
  302
  303
  304
  305
  306
  307
  308
  309
  310
  311
  312
  313
  314
  315
  316
  317
  318
  319
  320
  321
  322
  323
  324
  325
  326
  327
  328
  329
  330
  331
  332
  333
  334
  335
  336
  337
  338
  339
  340
  341
  342
  343
  344
  345
//===--- TargetCXXABI.h - C++ ABI Target Configuration ----------*- 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
/// Defines the TargetCXXABI class, which abstracts details of the
/// C++ ABI that we're targeting.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_BASIC_TARGETCXXABI_H
#define LLVM_CLANG_BASIC_TARGETCXXABI_H

#include "llvm/Support/ErrorHandling.h"

namespace clang {

/// The basic abstraction for the target C++ ABI.
class TargetCXXABI {
public:
  /// The basic C++ ABI kind.
  enum Kind {
    /// The generic Itanium ABI is the standard ABI of most open-source
    /// and Unix-like platforms.  It is the primary ABI targeted by
    /// many compilers, including Clang and GCC.
    ///
    /// It is documented here:
    ///   http://www.codesourcery.com/public/cxx-abi/
    GenericItanium,

    /// The generic ARM ABI is a modified version of the Itanium ABI
    /// proposed by ARM for use on ARM-based platforms.
    ///
    /// These changes include:
    ///   - the representation of member function pointers is adjusted
    ///     to not conflict with the 'thumb' bit of ARM function pointers;
    ///   - constructors and destructors return 'this';
    ///   - guard variables are smaller;
    ///   - inline functions are never key functions;
    ///   - array cookies have a slightly different layout;
    ///   - additional convenience functions are specified;
    ///   - and more!
    ///
    /// It is documented here:
    ///    http://infocenter.arm.com
    ///                    /help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf
    GenericARM,

    /// The iOS ABI is a partial implementation of the ARM ABI.
    /// Several of the features of the ARM ABI were not fully implemented
    /// in the compilers that iOS was launched with.
    ///
    /// Essentially, the iOS ABI includes the ARM changes to:
    ///   - member function pointers,
    ///   - guard variables,
    ///   - array cookies, and
    ///   - constructor/destructor signatures.
    iOS,

    /// The iOS 64-bit ABI is follows ARM's published 64-bit ABI more
    /// closely, but we don't guarantee to follow it perfectly.
    ///
    /// It is documented here:
    ///    http://infocenter.arm.com
    ///                  /help/topic/com.arm.doc.ihi0059a/IHI0059A_cppabi64.pdf
    iOS64,

    /// WatchOS is a modernisation of the iOS ABI, which roughly means it's
    /// the iOS64 ABI ported to 32-bits. The primary difference from iOS64 is
    /// that RTTI objects must still be unique at the moment.
    WatchOS,

    /// The generic AArch64 ABI is also a modified version of the Itanium ABI,
    /// but it has fewer divergences than the 32-bit ARM ABI.
    ///
    /// The relevant changes from the generic ABI in this case are:
    ///   - representation of member function pointers adjusted as in ARM.
    ///   - guard variables  are smaller.
    GenericAArch64,

    /// The generic Mips ABI is a modified version of the Itanium ABI.
    ///
    /// At the moment, only change from the generic ABI in this case is:
    ///   - representation of member function pointers adjusted as in ARM.
    GenericMIPS,

    /// The WebAssembly ABI is a modified version of the Itanium ABI.
    ///
    /// The changes from the Itanium ABI are:
    ///   - representation of member function pointers is adjusted, as in ARM;
    ///   - member functions are not specially aligned;
    ///   - constructors and destructors return 'this', as in ARM;
    ///   - guard variables are 32-bit on wasm32, as in ARM;
    ///   - unused bits of guard variables are reserved, as in ARM;
    ///   - inline functions are never key functions, as in ARM;
    ///   - C++11 POD rules are used for tail padding, as in iOS64.
    ///
    /// TODO: At present the WebAssembly ABI is not considered stable, so none
    /// of these details is necessarily final yet.
    WebAssembly,

    /// The Microsoft ABI is the ABI used by Microsoft Visual Studio (and
    /// compatible compilers).
    ///
    /// FIXME: should this be split into Win32 and Win64 variants?
    ///
    /// Only scattered and incomplete official documentation exists.
    Microsoft
  };

private:
  // Right now, this class is passed around as a cheap value type.
  // If you add more members, especially non-POD members, please
  // audit the users to pass it by reference instead.
  Kind TheKind;

public:
  /// A bogus initialization of the platform ABI.
  TargetCXXABI() : TheKind(GenericItanium) {}

  TargetCXXABI(Kind kind) : TheKind(kind) {}

  void set(Kind kind) {
    TheKind = kind;
  }

  Kind getKind() const { return TheKind; }

  /// Does this ABI generally fall into the Itanium family of ABIs?
  bool isItaniumFamily() const {
    switch (getKind()) {
    case GenericAArch64:
    case GenericItanium:
    case GenericARM:
    case iOS:
    case iOS64:
    case WatchOS:
    case GenericMIPS:
    case WebAssembly:
      return true;

    case Microsoft:
      return false;
    }
    llvm_unreachable("bad ABI kind");
  }

  /// Is this ABI an MSVC-compatible ABI?
  bool isMicrosoft() const {
    switch (getKind()) {
    case GenericAArch64:
    case GenericItanium:
    case GenericARM:
    case iOS:
    case iOS64:
    case WatchOS:
    case GenericMIPS:
    case WebAssembly:
      return false;

    case Microsoft:
      return true;
    }
    llvm_unreachable("bad ABI kind");
  }

  /// Are member functions differently aligned?
  ///
  /// Many Itanium-style C++ ABIs require member functions to be aligned, so
  /// that a pointer to such a function is guaranteed to have a zero in the
  /// least significant bit, so that pointers to member functions can use that
  /// bit to distinguish between virtual and non-virtual functions. However,
  /// some Itanium-style C++ ABIs differentiate between virtual and non-virtual
  /// functions via other means, and consequently don't require that member
  /// functions be aligned.
  bool areMemberFunctionsAligned() const {
    switch (getKind()) {
    case WebAssembly:
      // WebAssembly doesn't require any special alignment for member functions.
      return false;
    case GenericARM:
    case GenericAArch64:
    case GenericMIPS:
      // TODO: ARM-style pointers to member functions put the discriminator in
      //       the this adjustment, so they don't require functions to have any
      //       special alignment and could therefore also return false.
    case GenericItanium:
    case iOS:
    case iOS64:
    case WatchOS:
    case Microsoft:
      return true;
    }
    llvm_unreachable("bad ABI kind");
  }

  /// Are arguments to a call destroyed left to right in the callee?
  /// This is a fundamental language change, since it implies that objects
  /// passed by value do *not* live to the end of the full expression.
  /// Temporaries passed to a function taking a const reference live to the end
  /// of the full expression as usual.  Both the caller and the callee must
  /// have access to the destructor, while only the caller needs the
  /// destructor if this is false.
  bool areArgsDestroyedLeftToRightInCallee() const {
    return isMicrosoft();
  }

  /// Does this ABI have different entrypoints for complete-object
  /// and base-subobject constructors?
  bool hasConstructorVariants() const {
    return isItaniumFamily();
  }

  /// Does this ABI allow virtual bases to be primary base classes?
  bool hasPrimaryVBases() const {
    return isItaniumFamily();
  }

  /// Does this ABI use key functions?  If so, class data such as the
  /// vtable is emitted with strong linkage by the TU containing the key
  /// function.
  bool hasKeyFunctions() const {
    return isItaniumFamily();
  }

  /// Can an out-of-line inline function serve as a key function?
  ///
  /// This flag is only useful in ABIs where type data (for example,
  /// vtables and type_info objects) are emitted only after processing
  /// the definition of a special "key" virtual function.  (This is safe
  /// because the ODR requires that every virtual function be defined
  /// somewhere in a program.)  This usually permits such data to be
  /// emitted in only a single object file, as opposed to redundantly
  /// in every object file that requires it.
  ///
  /// One simple and common definition of "key function" is the first
  /// virtual function in the class definition which is not defined there.
  /// This rule works very well when that function has a non-inline
  /// definition in some non-header file.  Unfortunately, when that
  /// function is defined inline, this rule requires the type data
  /// to be emitted weakly, as if there were no key function.
  ///
  /// The ARM ABI observes that the ODR provides an additional guarantee:
  /// a virtual function is always ODR-used, so if it is defined inline,
  /// that definition must appear in every translation unit that defines
  /// the class.  Therefore, there is no reason to allow such functions
  /// to serve as key functions.
  ///
  /// Because this changes the rules for emitting type data,
  /// it can cause type data to be emitted with both weak and strong
  /// linkage, which is not allowed on all platforms.  Therefore,
  /// exploiting this observation requires an ABI break and cannot be
  /// done on a generic Itanium platform.
  bool canKeyFunctionBeInline() const {
    switch (getKind()) {
    case GenericARM:
    case iOS64:
    case WebAssembly:
    case WatchOS:
      return false;

    case GenericAArch64:
    case GenericItanium:
    case iOS:   // old iOS compilers did not follow this rule
    case Microsoft:
    case GenericMIPS:
      return true;
    }
    llvm_unreachable("bad ABI kind");
  }

  /// When is record layout allowed to allocate objects in the tail
  /// padding of a base class?
  ///
  /// This decision cannot be changed without breaking platform ABI
  /// compatibility, and yet it is tied to language guarantees which
  /// the committee has so far seen fit to strengthen no less than
  /// three separate times:
  ///   - originally, there were no restrictions at all;
  ///   - C++98 declared that objects could not be allocated in the
  ///     tail padding of a POD type;
  ///   - C++03 extended the definition of POD to include classes
  ///     containing member pointers; and
  ///   - C++11 greatly broadened the definition of POD to include
  ///     all trivial standard-layout classes.
  /// Each of these changes technically took several existing
  /// platforms and made them permanently non-conformant.
  enum TailPaddingUseRules {
    /// The tail-padding of a base class is always theoretically
    /// available, even if it's POD.  This is not strictly conforming
    /// in any language mode.
    AlwaysUseTailPadding,

    /// Only allocate objects in the tail padding of a base class if
    /// the base class is not POD according to the rules of C++ TR1.
    /// This is non-strictly conforming in C++11 mode.
    UseTailPaddingUnlessPOD03,

    /// Only allocate objects in the tail padding of a base class if
    /// the base class is not POD according to the rules of C++11.
    UseTailPaddingUnlessPOD11
  };
  TailPaddingUseRules getTailPaddingUseRules() const {
    switch (getKind()) {
    // To preserve binary compatibility, the generic Itanium ABI has
    // permanently locked the definition of POD to the rules of C++ TR1,
    // and that trickles down to derived ABIs.
    case GenericItanium:
    case GenericAArch64:
    case GenericARM:
    case iOS:
    case GenericMIPS:
      return UseTailPaddingUnlessPOD03;

    // iOS on ARM64 and WebAssembly use the C++11 POD rules.  They do not honor
    // the Itanium exception about classes with over-large bitfields.
    case iOS64:
    case WebAssembly:
    case WatchOS:
      return UseTailPaddingUnlessPOD11;

    // MSVC always allocates fields in the tail-padding of a base class
    // subobject, even if they're POD.
    case Microsoft:
      return AlwaysUseTailPadding;
    }
    llvm_unreachable("bad ABI kind");
  }

  friend bool operator==(const TargetCXXABI &left, const TargetCXXABI &right) {
    return left.getKind() == right.getKind();
  }

  friend bool operator!=(const TargetCXXABI &left, const TargetCXXABI &right) {
    return !(left == right);
  }
};

}  // end namespace clang

#endif