123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===--- 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 <map>
- #include "clang/Basic/LLVM.h"
- #include "llvm/ADT/StringMap.h"
- #include "llvm/ADT/Triple.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 {
- #define CXXABI(Name, Str) Name,
- #include "TargetCXXABI.def"
- };
- 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;
- static const auto &getABIMap() {
- static llvm::StringMap<Kind> ABIMap = {
- #define CXXABI(Name, Str) {Str, Name},
- #include "TargetCXXABI.def"
- };
- return ABIMap;
- }
- static const auto &getSpellingMap() {
- static std::map<Kind, std::string> SpellingMap = {
- #define CXXABI(Name, Str) {Name, Str},
- #include "TargetCXXABI.def"
- };
- return SpellingMap;
- }
- public:
- static Kind getKind(StringRef Name) { return getABIMap().lookup(Name); }
- static const auto &getSpelling(Kind ABIKind) {
- return getSpellingMap().find(ABIKind)->second;
- }
- static bool isABI(StringRef Name) {
- return getABIMap().find(Name) != getABIMap().end();
- }
- // Return true if this target should use the relative vtables C++ ABI by
- // default.
- static bool usesRelativeVTables(const llvm::Triple &T) {
- return T.isOSFuchsia();
- }
- /// 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; }
- // Check that the kind provided by the fc++-abi flag is supported on this
- // target. Users who want to experiment using different ABIs on specific
- // platforms can change this freely, but this function should be conservative
- // enough such that not all ABIs are allowed on all platforms. For example, we
- // probably don't want to allow usage of an ARM ABI on an x86 architecture.
- static bool isSupportedCXXABI(const llvm::Triple &T, Kind Kind) {
- switch (Kind) {
- case GenericARM:
- return T.isARM() || T.isAArch64();
- case iOS:
- case WatchOS:
- case AppleARM64:
- return T.isOSDarwin();
- case Fuchsia:
- return T.isOSFuchsia();
- case GenericAArch64:
- return T.isAArch64();
- case GenericMIPS:
- return T.isMIPS();
- case WebAssembly:
- return T.isWasm();
- case XL:
- return T.isOSAIX();
- case GenericItanium:
- return true;
- case Microsoft:
- return T.isKnownWindowsMSVCEnvironment();
- }
- llvm_unreachable("invalid CXXABI kind");
- };
- /// Does this ABI generally fall into the Itanium family of ABIs?
- bool isItaniumFamily() const {
- switch (getKind()) {
- #define CXXABI(Name, Str)
- #define ITANIUM_CXXABI(Name, Str) case Name:
- #include "TargetCXXABI.def"
- return true;
- default:
- return false;
- }
- llvm_unreachable("bad ABI kind");
- }
- /// Is this ABI an MSVC-compatible ABI?
- bool isMicrosoft() const {
- switch (getKind()) {
- #define CXXABI(Name, Str)
- #define MICROSOFT_CXXABI(Name, Str) case Name:
- #include "TargetCXXABI.def"
- return true;
- default:
- return false;
- }
- 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 AppleARM64:
- case Fuchsia:
- 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 WatchOS:
- case Microsoft:
- case XL:
- 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 AppleARM64:
- case Fuchsia:
- case GenericARM:
- case WebAssembly:
- case WatchOS:
- return false;
- case GenericAArch64:
- case GenericItanium:
- case iOS: // old iOS compilers did not follow this rule
- case Microsoft:
- case GenericMIPS:
- case XL:
- 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. In ISO C++98, tail padding reuse was only permitted for
- /// non-POD base classes, but that restriction was removed retroactively by
- /// DR 43, and tail padding reuse is always permitted in all de facto C++
- /// language modes. However, many platforms use a variant of the old C++98
- /// rule for compatibility.
- enum TailPaddingUseRules {
- /// The tail-padding of a base class is always theoretically
- /// available, even if it's POD.
- 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.
- 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:
- case XL:
- return UseTailPaddingUnlessPOD03;
- // AppleARM64 and WebAssembly use the C++11 POD rules. They do not honor
- // the Itanium exception about classes with over-large bitfields.
- case AppleARM64:
- case Fuchsia:
- 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
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|