leonardchan updated this revision to Diff 339753. leonardchan marked an inline comment as done.
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D85802/new/ https://reviews.llvm.org/D85802 Files: clang/include/clang/AST/ASTContext.h clang/include/clang/Basic/DiagnosticDriverKinds.td clang/include/clang/Basic/LangOptions.h clang/include/clang/Basic/TargetCXXABI.def clang/include/clang/Basic/TargetCXXABI.h clang/include/clang/Driver/Options.td clang/lib/AST/ASTContext.cpp clang/lib/CodeGen/CodeGenModule.cpp clang/lib/CodeGen/ItaniumCXXABI.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/test/CodeGenCXX/cxx-abi-switch.cpp clang/test/Frontend/invalid-cxx-abi.cpp
Index: clang/test/Frontend/invalid-cxx-abi.cpp =================================================================== --- /dev/null +++ clang/test/Frontend/invalid-cxx-abi.cpp @@ -0,0 +1,30 @@ +// These should succeed. +// RUN: %clang -c -fc++-abi=itanium %s +// RUN: %clang -c -fc++-abi=arm %s +// RUN: %clang -c -fc++-abi=ios %s +// RUN: %clang -c -fc++-abi=aarch64 %s +// RUN: %clang -c -fc++-abi=mips %s +// RUN: %clang -c -fc++-abi=webassembly %s +// RUN: %clang -c -fc++-abi=fuchsia %s +// RUN: %clang -c -fc++-abi=xl %s +// RUN: %clang -c -fc++-abi=microsoft %s +// RUN: %clang_cc1 -fc++-abi=itanium %s +// RUN: %clang_cc1 -fc++-abi=arm %s +// RUN: %clang_cc1 -fc++-abi=ios %s +// RUN: %clang_cc1 -fc++-abi=aarch64 %s +// RUN: %clang_cc1 -fc++-abi=mips %s +// RUN: %clang_cc1 -fc++-abi=webassembly %s +// RUN: %clang_cc1 -fc++-abi=fuchsia %s +// RUN: %clang_cc1 -fc++-abi=xl %s +// RUN: %clang_cc1 -fc++-abi=microsoft %s + +// RUN: not %clang -c -fc++-abi=InvalidABI %s 2>&1 | FileCheck %s -check-prefix=INVALID +// RUN: not %clang -c -fc++-abi=Fuchsia %s 2>&1 | FileCheck %s -check-prefix=CASE-SENSITIVE +// RUN: not %clang_cc1 -fc++-abi=InvalidABI %s 2>&1 | FileCheck %s -check-prefix=INVALID +// RUN: not %clang_cc1 -fc++-abi=Fuchsia %s 2>&1 | FileCheck %s -check-prefix=CASE-SENSITIVE +// INVALID: error: Invalid C++ ABI name 'InvalidABI' +// CASE-SENSITIVE: error: Invalid C++ ABI name 'Fuchsia' + +// The flag is propgated from the driver to cc1. +// RUN: %clang -fc++-abi=InvalidABI %s -### 2>&1 | FileCheck %s -check-prefix=CC1-FLAG +// CC1-FLAG: -fc++-abi=InvalidABI Index: clang/test/CodeGenCXX/cxx-abi-switch.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/cxx-abi-switch.cpp @@ -0,0 +1,27 @@ +// Assert that the ABI switch uses the proper codegen. Fuchsia uses the +// "return this" ABI on constructors and destructors by default, so we can just +// check that ABI is used regardless of the target. +// +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-unknown-linux-gnu -fc++-abi=fuchsia | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=aarch64-unknown-linux-gnu -fc++-abi=fuchsia | FileCheck %s + +class A { +public: + virtual ~A(); + int x_; +}; + +class B : public A { +public: + B(int *i); + virtual ~B(); + int *i_; +}; + +B::B(int *i) : i_(i) {} +B::~B() {} + +// CHECK: define{{.*}} %class.B* @_ZN1BC2EPi(%class.B* {{[^,]*}} returned {{[^,]*}} %this, i32* %i) +// CHECK: define{{.*}} %class.B* @_ZN1BC1EPi(%class.B* {{[^,]*}} returned {{[^,]*}} %this, i32* %i) +// CHECK: define{{.*}} %class.B* @_ZN1BD2Ev(%class.B* {{[^,]*}} returned {{[^,]*}} %this) +// CHECK: define{{.*}} %class.B* @_ZN1BD1Ev(%class.B* {{[^,]*}} returned {{[^,]*}} %this) Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -3506,6 +3506,10 @@ if (Opts.getSignReturnAddressKey() == LangOptions::SignReturnAddressKeyKind::BKey) GenerateArg(Args, OPT_msign_return_address_key_EQ, "b_key", SA); + + if (Opts.CXXABI) + GenerateArg(Args, OPT_fcxx_abi_EQ, TargetCXXABI::getSpelling(*Opts.CXXABI), + SA); } bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, @@ -3989,6 +3993,15 @@ } } + // The value can be empty, which indicates the system default should be used. + StringRef CXXABI = Args.getLastArgValue(OPT_fcxx_abi_EQ); + if (!CXXABI.empty()) { + if (!TargetCXXABI::isABI(CXXABI)) + Diags.Report(diag::err_invalid_cxx_abi) << CXXABI; + else + Opts.CXXABI = TargetCXXABI::getKind(CXXABI); + } + return Diags.getNumErrors() == NumErrorsBefore; } Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -5307,6 +5307,9 @@ /*Default=*/false)) Args.AddLastArg(CmdArgs, options::OPT_ffixed_point); + if (Arg *A = Args.getLastArg(options::OPT_fcxx_abi_EQ)) + A->render(Args, CmdArgs); + // Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi} // (-ansi is equivalent to -std=c89 or -std=c++98). // Index: clang/lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- clang/lib/CodeGen/ItaniumCXXABI.cpp +++ clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -546,7 +546,7 @@ } CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { - switch (CGM.getTarget().getCXXABI().getKind()) { + switch (CGM.getContext().getCXXABIKind()) { // For IR-generation purposes, there's no significant difference // between the ARM and iOS ABIs. case TargetCXXABI::GenericARM: Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -75,7 +75,7 @@ static const char AnnotationSection[] = "llvm.metadata"; static CGCXXABI *createCXXABI(CodeGenModule &CGM) { - switch (CGM.getTarget().getCXXABI().getKind()) { + switch (CGM.getContext().getCXXABIKind()) { case TargetCXXABI::AppleARM64: case TargetCXXABI::Fuchsia: case TargetCXXABI::GenericAArch64: Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -880,10 +880,15 @@ return CanonTTP; } +TargetCXXABI::Kind ASTContext::getCXXABIKind() const { + auto Kind = getTargetInfo().getCXXABI().getKind(); + return getLangOpts().CXXABI.getValueOr(Kind); +} + CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { if (!LangOpts.CPlusPlus) return nullptr; - switch (T.getCXXABI().getKind()) { + switch (getCXXABIKind()) { case TargetCXXABI::AppleARM64: case TargetCXXABI::Fuchsia: case TargetCXXABI::GenericARM: // Same as Itanium at this level Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -1878,6 +1878,10 @@ PosFlag<SetTrue, [], "Use">, NegFlag<SetFalse, [], "Do not use">, BothFlags<[CC1Option], " the experimental C++ class ABI for classes with virtual tables">>; +def fcxx_abi_EQ : Joined<["-"], "fc++-abi=">, + Group<f_clang_Group>, Flags<[CC1Option]>, + HelpText<"C++ ABI to use. This will override the target C++ ABI.">; + def flat__namespace : Flag<["-"], "flat_namespace">; def flax_vector_conversions_EQ : Joined<["-"], "flax-vector-conversions=">, Group<f_Group>, HelpText<"Enable implicit vector bit-casts">, Values<"none,integer,all">, Flags<[CC1Option]>, Index: clang/include/clang/Basic/TargetCXXABI.h =================================================================== --- clang/include/clang/Basic/TargetCXXABI.h +++ clang/include/clang/Basic/TargetCXXABI.h @@ -15,7 +15,10 @@ #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/Support/ErrorHandling.h" namespace clang { @@ -25,105 +28,8 @@ 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 and macOS 64-bit ARM ABI 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 - AppleARM64, - - /// WatchOS is a modernisation of the iOS ABI, which roughly means it's - /// the AppleARM64 ABI ported to 32-bits. The primary difference from - /// AppleARM64 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 AppleARM64. - /// - /// TODO: At present the WebAssembly ABI is not considered stable, so none - /// of these details is necessarily final yet. - WebAssembly, - - /// The Fuchsia ABI is a modified version of the Itanium ABI. - /// - /// The relevant changes from the Itanium ABI are: - /// - constructors and destructors return 'this', as in ARM. - Fuchsia, - - /// The XL ABI is the ABI used by IBM xlclang compiler and is a modified - /// version of the Itanium ABI. - /// - /// The relevant changes from the Itanium ABI are: - /// - static initialization is adjusted to use sinit and sterm functions; - XL, - - /// 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 +#define CXXABI(Name, Str) Name, +#include "TargetCXXABI.def" }; private: @@ -132,7 +38,31 @@ // 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(); + } + /// A bogus initialization of the platform ABI. TargetCXXABI() : TheKind(GenericItanium) {} @@ -147,19 +77,12 @@ /// Does this ABI generally fall into the Itanium family of ABIs? bool isItaniumFamily() const { switch (getKind()) { - case AppleARM64: - case Fuchsia: - case GenericAArch64: - case GenericItanium: - case GenericARM: - case iOS: - case WatchOS: - case GenericMIPS: - case WebAssembly: - case XL: +#define CXXABI(Name, Str) +#define ITANIUM_CXXABI(Name, Str) case Name: +#include "TargetCXXABI.def" return true; - case Microsoft: + default: return false; } llvm_unreachable("bad ABI kind"); @@ -168,20 +91,13 @@ /// Is this ABI an MSVC-compatible ABI? bool isMicrosoft() const { switch (getKind()) { - case AppleARM64: - case Fuchsia: - case GenericAArch64: - case GenericItanium: - case GenericARM: - case iOS: - case WatchOS: - case GenericMIPS: - case WebAssembly: - case XL: - return false; - - case Microsoft: +#define CXXABI(Name, Str) +#define MICROSOFT_CXXABI(Name, Str) case Name: +#include "TargetCXXABI.def" return true; + + default: + return false; } llvm_unreachable("bad ABI kind"); } Index: clang/include/clang/Basic/TargetCXXABI.def =================================================================== --- /dev/null +++ clang/include/clang/Basic/TargetCXXABI.def @@ -0,0 +1,129 @@ +//===--- TargetCXXABI.def - Target C++ ABI database --------------- 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 +// +//===----------------------------------------------------------------------===// +// +// This file defines the various C++ ABI kinds used on different platforms. +// Users of this file must define the CXXABI macro to make use of this +// information. +// +//===----------------------------------------------------------------------===// + +#ifndef CXXABI +#error Define the CXXABI macro to handle C++ ABI kinds. +#endif + +#ifndef ITANIUM_CXXABI +#define ITANIUM_CXXABI(Name, Str) CXXABI(Name, Str) +#endif + +#ifndef MICROSOFT_CXXABI +#define MICROSOFT_CXXABI(Name, Str) CXXABI(Name, Str) +#endif + +/// 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/ +ITANIUM_CXXABI(GenericItanium, "itanium") + +/// 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 +ITANIUM_CXXABI(GenericARM, "arm") + +/// 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. +ITANIUM_CXXABI(iOS, "ios") + +/// The iOS 64-bit and macOS 64-bit ARM ABI 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 +ITANIUM_CXXABI(AppleARM64, "applearm64") + +/// 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. +ITANIUM_CXXABI(WatchOS, "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. +ITANIUM_CXXABI(GenericAArch64, "aarch64") + +/// 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. +ITANIUM_CXXABI(GenericMIPS, "mips") + +/// 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. +ITANIUM_CXXABI(WebAssembly, "webassembly") + +/// The Fuchsia ABI is a modified version of the Itanium ABI. +/// +/// The relevant changes from the Itanium ABI are: +/// - constructors and destructors return 'this', as in ARM. +ITANIUM_CXXABI(Fuchsia, "fuchsia") + +/// The XL ABI is the ABI used by IBM xlclang compiler and is a modified +/// version of the Itanium ABI. +/// +/// The relevant changes from the Itanium ABI are: +/// - static initialization is adjusted to use sinit and sterm functions; +ITANIUM_CXXABI(XL, "xl") + +/// 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_CXXABI(Microsoft, "microsoft") + +#undef CXXABI +#undef ITANIUM_CXXABI +#undef MICROSOFT_CXXABI Index: clang/include/clang/Basic/LangOptions.h =================================================================== --- clang/include/clang/Basic/LangOptions.h +++ clang/include/clang/Basic/LangOptions.h @@ -19,6 +19,7 @@ #include "clang/Basic/LangStandard.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Sanitizers.h" +#include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/Visibility.h" #include "llvm/ADT/FloatingPointMode.h" #include "llvm/ADT/StringRef.h" @@ -338,6 +339,10 @@ /// like CUDA/HIP. std::string CUID; + /// C++ ABI to compile with, if specified by the frontend through -fc++-abi=. + /// This overrides the default ABI used by the target. + llvm::Optional<TargetCXXABI::Kind> CXXABI; + /// Indicates whether the front-end is explicitly told that the /// input is a header file (i.e. -x c-header). bool IsHeaderFile = false; Index: clang/include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticDriverKinds.td +++ clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -536,6 +536,8 @@ def err_aix_default_altivec_abi : Error< "The default Altivec ABI on AIX is not yet supported, use '-mabi=vec-extabi' for the extended Altivec ABI">; +def err_invalid_cxx_abi : Error<"Invalid C++ ABI name '%0'">; + def note_cc1_round_trip_original : Note<"Original arguments in round-trip: %0">; def note_cc1_round_trip_generated : Note<"Generated arguments #%0 in round-trip: %1">; def remark_cc1_round_trip_generated : Remark<"Generated arguments #%0 in round-trip: %1">, InGroup<RoundTripCC1Args>; Index: clang/include/clang/AST/ASTContext.h =================================================================== --- clang/include/clang/AST/ASTContext.h +++ clang/include/clang/AST/ASTContext.h @@ -40,6 +40,7 @@ #include "clang/Basic/ProfileList.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" +#include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/XRayLists.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" @@ -730,6 +731,11 @@ return FullSourceLoc(Loc,SourceMgr); } + /// Return the C++ ABI kind that should be used. The C++ ABI can be overriden + /// at compile time with `-fc++-abi=`. If this is not provided, we instead use + /// the default ABI set by the target. + TargetCXXABI::Kind getCXXABIKind() const; + /// All comments in this translation unit. RawCommentList Comments;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits