10b57cec5SDimitry Andric //===------- ItaniumCXXABI.cpp - AST support for the Itanium C++ ABI ------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This provides C++ AST support targeting the Itanium C++ ABI, which is
100b57cec5SDimitry Andric // documented at:
110b57cec5SDimitry Andric // http://www.codesourcery.com/public/cxx-abi/abi.html
120b57cec5SDimitry Andric // http://www.codesourcery.com/public/cxx-abi/abi-eh.html
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric // It also supports the closely-related ARM C++ ABI, documented at:
150b57cec5SDimitry Andric // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf
160b57cec5SDimitry Andric //
170b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
180b57cec5SDimitry Andric
190b57cec5SDimitry Andric #include "CXXABI.h"
200b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
210b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
22a7dea167SDimitry Andric #include "clang/AST/Mangle.h"
230b57cec5SDimitry Andric #include "clang/AST/MangleNumberingContext.h"
240b57cec5SDimitry Andric #include "clang/AST/RecordLayout.h"
250b57cec5SDimitry Andric #include "clang/AST/Type.h"
260b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
27a7dea167SDimitry Andric #include "llvm/ADT/FoldingSet.h"
280b57cec5SDimitry Andric #include "llvm/ADT/iterator.h"
29*bdd1243dSDimitry Andric #include <optional>
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric using namespace clang;
320b57cec5SDimitry Andric
330b57cec5SDimitry Andric namespace {
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric /// According to Itanium C++ ABI 5.1.2:
360b57cec5SDimitry Andric /// the name of an anonymous union is considered to be
370b57cec5SDimitry Andric /// the name of the first named data member found by a pre-order,
380b57cec5SDimitry Andric /// depth-first, declaration-order walk of the data members of
390b57cec5SDimitry Andric /// the anonymous union.
400b57cec5SDimitry Andric /// If there is no such data member (i.e., if all of the data members
410b57cec5SDimitry Andric /// in the union are unnamed), then there is no way for a program to
420b57cec5SDimitry Andric /// refer to the anonymous union, and there is therefore no need to mangle its name.
430b57cec5SDimitry Andric ///
440b57cec5SDimitry Andric /// Returns the name of anonymous union VarDecl or nullptr if it is not found.
findAnonymousUnionVarDeclName(const VarDecl & VD)450b57cec5SDimitry Andric static const IdentifierInfo *findAnonymousUnionVarDeclName(const VarDecl& VD) {
460b57cec5SDimitry Andric const RecordType *RT = VD.getType()->getAs<RecordType>();
470b57cec5SDimitry Andric assert(RT && "type of VarDecl is expected to be RecordType.");
480b57cec5SDimitry Andric assert(RT->getDecl()->isUnion() && "RecordType is expected to be a union.");
490b57cec5SDimitry Andric if (const FieldDecl *FD = RT->getDecl()->findFirstNamedDataMember()) {
500b57cec5SDimitry Andric return FD->getIdentifier();
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric return nullptr;
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric
560b57cec5SDimitry Andric /// The name of a decomposition declaration.
570b57cec5SDimitry Andric struct DecompositionDeclName {
580b57cec5SDimitry Andric using BindingArray = ArrayRef<const BindingDecl*>;
590b57cec5SDimitry Andric
600b57cec5SDimitry Andric /// Representative example of a set of bindings with these names.
610b57cec5SDimitry Andric BindingArray Bindings;
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric /// Iterators over the sequence of identifiers in the name.
640b57cec5SDimitry Andric struct Iterator
650b57cec5SDimitry Andric : llvm::iterator_adaptor_base<Iterator, BindingArray::const_iterator,
660b57cec5SDimitry Andric std::random_access_iterator_tag,
670b57cec5SDimitry Andric const IdentifierInfo *> {
Iterator__anone02e58390111::DecompositionDeclName::Iterator680b57cec5SDimitry Andric Iterator(BindingArray::const_iterator It) : iterator_adaptor_base(It) {}
operator *__anone02e58390111::DecompositionDeclName::Iterator690b57cec5SDimitry Andric const IdentifierInfo *operator*() const {
700b57cec5SDimitry Andric return (*this->I)->getIdentifier();
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric };
begin__anone02e58390111::DecompositionDeclName730b57cec5SDimitry Andric Iterator begin() const { return Iterator(Bindings.begin()); }
end__anone02e58390111::DecompositionDeclName740b57cec5SDimitry Andric Iterator end() const { return Iterator(Bindings.end()); }
750b57cec5SDimitry Andric };
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric
780b57cec5SDimitry Andric namespace llvm {
isDenseMapKeyEmpty(T V)79a7dea167SDimitry Andric template<typename T> bool isDenseMapKeyEmpty(T V) {
80a7dea167SDimitry Andric return llvm::DenseMapInfo<T>::isEqual(
81a7dea167SDimitry Andric V, llvm::DenseMapInfo<T>::getEmptyKey());
82a7dea167SDimitry Andric }
isDenseMapKeyTombstone(T V)83a7dea167SDimitry Andric template<typename T> bool isDenseMapKeyTombstone(T V) {
84a7dea167SDimitry Andric return llvm::DenseMapInfo<T>::isEqual(
85a7dea167SDimitry Andric V, llvm::DenseMapInfo<T>::getTombstoneKey());
86a7dea167SDimitry Andric }
87a7dea167SDimitry Andric
88a7dea167SDimitry Andric template <typename T>
areDenseMapKeysEqualSpecialValues(T LHS,T RHS)89*bdd1243dSDimitry Andric std::optional<bool> areDenseMapKeysEqualSpecialValues(T LHS, T RHS) {
90a7dea167SDimitry Andric bool LHSEmpty = isDenseMapKeyEmpty(LHS);
91a7dea167SDimitry Andric bool RHSEmpty = isDenseMapKeyEmpty(RHS);
92a7dea167SDimitry Andric if (LHSEmpty || RHSEmpty)
93a7dea167SDimitry Andric return LHSEmpty && RHSEmpty;
94a7dea167SDimitry Andric
95a7dea167SDimitry Andric bool LHSTombstone = isDenseMapKeyTombstone(LHS);
96a7dea167SDimitry Andric bool RHSTombstone = isDenseMapKeyTombstone(RHS);
97a7dea167SDimitry Andric if (LHSTombstone || RHSTombstone)
98a7dea167SDimitry Andric return LHSTombstone && RHSTombstone;
99a7dea167SDimitry Andric
100*bdd1243dSDimitry Andric return std::nullopt;
101a7dea167SDimitry Andric }
102a7dea167SDimitry Andric
1030b57cec5SDimitry Andric template<>
1040b57cec5SDimitry Andric struct DenseMapInfo<DecompositionDeclName> {
1050b57cec5SDimitry Andric using ArrayInfo = llvm::DenseMapInfo<ArrayRef<const BindingDecl*>>;
getEmptyKeyllvm::DenseMapInfo1060b57cec5SDimitry Andric static DecompositionDeclName getEmptyKey() {
1070b57cec5SDimitry Andric return {ArrayInfo::getEmptyKey()};
1080b57cec5SDimitry Andric }
getTombstoneKeyllvm::DenseMapInfo1090b57cec5SDimitry Andric static DecompositionDeclName getTombstoneKey() {
1100b57cec5SDimitry Andric return {ArrayInfo::getTombstoneKey()};
1110b57cec5SDimitry Andric }
getHashValuellvm::DenseMapInfo1120b57cec5SDimitry Andric static unsigned getHashValue(DecompositionDeclName Key) {
1130b57cec5SDimitry Andric assert(!isEqual(Key, getEmptyKey()) && !isEqual(Key, getTombstoneKey()));
1140b57cec5SDimitry Andric return llvm::hash_combine_range(Key.begin(), Key.end());
1150b57cec5SDimitry Andric }
isEqualllvm::DenseMapInfo1160b57cec5SDimitry Andric static bool isEqual(DecompositionDeclName LHS, DecompositionDeclName RHS) {
117*bdd1243dSDimitry Andric if (std::optional<bool> Result =
118*bdd1243dSDimitry Andric areDenseMapKeysEqualSpecialValues(LHS.Bindings, RHS.Bindings))
119a7dea167SDimitry Andric return *Result;
120a7dea167SDimitry Andric
1210b57cec5SDimitry Andric return LHS.Bindings.size() == RHS.Bindings.size() &&
1220b57cec5SDimitry Andric std::equal(LHS.begin(), LHS.end(), RHS.begin());
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric };
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric namespace {
1280b57cec5SDimitry Andric
1290b57cec5SDimitry Andric /// Keeps track of the mangled names of lambda expressions and block
1300b57cec5SDimitry Andric /// literals within a particular context.
1310b57cec5SDimitry Andric class ItaniumNumberingContext : public MangleNumberingContext {
132a7dea167SDimitry Andric ItaniumMangleContext *Mangler;
133a7dea167SDimitry Andric llvm::StringMap<unsigned> LambdaManglingNumbers;
134a7dea167SDimitry Andric unsigned BlockManglingNumber = 0;
1350b57cec5SDimitry Andric llvm::DenseMap<const IdentifierInfo *, unsigned> VarManglingNumbers;
1360b57cec5SDimitry Andric llvm::DenseMap<const IdentifierInfo *, unsigned> TagManglingNumbers;
1370b57cec5SDimitry Andric llvm::DenseMap<DecompositionDeclName, unsigned>
1380b57cec5SDimitry Andric DecompsitionDeclManglingNumbers;
1390b57cec5SDimitry Andric
1400b57cec5SDimitry Andric public:
ItaniumNumberingContext(ItaniumMangleContext * Mangler)141a7dea167SDimitry Andric ItaniumNumberingContext(ItaniumMangleContext *Mangler) : Mangler(Mangler) {}
1420b57cec5SDimitry Andric
getManglingNumber(const CXXMethodDecl * CallOperator)143a7dea167SDimitry Andric unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
144a7dea167SDimitry Andric const CXXRecordDecl *Lambda = CallOperator->getParent();
145a7dea167SDimitry Andric assert(Lambda->isLambda());
146a7dea167SDimitry Andric
147a7dea167SDimitry Andric // Computation of the <lambda-sig> is non-trivial and subtle. Rather than
148a7dea167SDimitry Andric // duplicating it here, just mangle the <lambda-sig> directly.
149a7dea167SDimitry Andric llvm::SmallString<128> LambdaSig;
150a7dea167SDimitry Andric llvm::raw_svector_ostream Out(LambdaSig);
151a7dea167SDimitry Andric Mangler->mangleLambdaSig(Lambda, Out);
152a7dea167SDimitry Andric
153a7dea167SDimitry Andric return ++LambdaManglingNumbers[LambdaSig];
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric
getManglingNumber(const BlockDecl * BD)1560b57cec5SDimitry Andric unsigned getManglingNumber(const BlockDecl *BD) override {
157a7dea167SDimitry Andric return ++BlockManglingNumber;
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric
getStaticLocalNumber(const VarDecl * VD)1600b57cec5SDimitry Andric unsigned getStaticLocalNumber(const VarDecl *VD) override {
1610b57cec5SDimitry Andric return 0;
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric
1640b57cec5SDimitry Andric /// Variable decls are numbered by identifier.
getManglingNumber(const VarDecl * VD,unsigned)1650b57cec5SDimitry Andric unsigned getManglingNumber(const VarDecl *VD, unsigned) override {
1660b57cec5SDimitry Andric if (auto *DD = dyn_cast<DecompositionDecl>(VD)) {
1670b57cec5SDimitry Andric DecompositionDeclName Name{DD->bindings()};
1680b57cec5SDimitry Andric return ++DecompsitionDeclManglingNumbers[Name];
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric
1710b57cec5SDimitry Andric const IdentifierInfo *Identifier = VD->getIdentifier();
1720b57cec5SDimitry Andric if (!Identifier) {
1730b57cec5SDimitry Andric // VarDecl without an identifier represents an anonymous union
1740b57cec5SDimitry Andric // declaration.
1750b57cec5SDimitry Andric Identifier = findAnonymousUnionVarDeclName(*VD);
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric return ++VarManglingNumbers[Identifier];
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric
getManglingNumber(const TagDecl * TD,unsigned)1800b57cec5SDimitry Andric unsigned getManglingNumber(const TagDecl *TD, unsigned) override {
1810b57cec5SDimitry Andric return ++TagManglingNumbers[TD->getIdentifier()];
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric };
1840b57cec5SDimitry Andric
185349cc55cSDimitry Andric // A version of this for SYCL that makes sure that 'device' mangling context
186349cc55cSDimitry Andric // matches the lambda mangling number, so that __builtin_sycl_unique_stable_name
187349cc55cSDimitry Andric // can be consistently generated between a MS and Itanium host by just referring
188349cc55cSDimitry Andric // to the device mangling number.
189349cc55cSDimitry Andric class ItaniumSYCLNumberingContext : public ItaniumNumberingContext {
190349cc55cSDimitry Andric llvm::DenseMap<const CXXMethodDecl *, unsigned> ManglingNumbers;
191349cc55cSDimitry Andric using ManglingItr = decltype(ManglingNumbers)::iterator;
192349cc55cSDimitry Andric
193349cc55cSDimitry Andric public:
ItaniumSYCLNumberingContext(ItaniumMangleContext * Mangler)194349cc55cSDimitry Andric ItaniumSYCLNumberingContext(ItaniumMangleContext *Mangler)
195349cc55cSDimitry Andric : ItaniumNumberingContext(Mangler) {}
196349cc55cSDimitry Andric
getManglingNumber(const CXXMethodDecl * CallOperator)197349cc55cSDimitry Andric unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
198349cc55cSDimitry Andric unsigned Number = ItaniumNumberingContext::getManglingNumber(CallOperator);
199349cc55cSDimitry Andric std::pair<ManglingItr, bool> emplace_result =
200349cc55cSDimitry Andric ManglingNumbers.try_emplace(CallOperator, Number);
201349cc55cSDimitry Andric (void)emplace_result;
202349cc55cSDimitry Andric assert(emplace_result.second && "Lambda number set multiple times?");
203349cc55cSDimitry Andric return Number;
204349cc55cSDimitry Andric }
205349cc55cSDimitry Andric
206349cc55cSDimitry Andric using ItaniumNumberingContext::getManglingNumber;
207349cc55cSDimitry Andric
getDeviceManglingNumber(const CXXMethodDecl * CallOperator)208349cc55cSDimitry Andric unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override {
209349cc55cSDimitry Andric ManglingItr Itr = ManglingNumbers.find(CallOperator);
210349cc55cSDimitry Andric assert(Itr != ManglingNumbers.end() && "Lambda not yet mangled?");
211349cc55cSDimitry Andric
212349cc55cSDimitry Andric return Itr->second;
213349cc55cSDimitry Andric }
214349cc55cSDimitry Andric };
215349cc55cSDimitry Andric
2160b57cec5SDimitry Andric class ItaniumCXXABI : public CXXABI {
217a7dea167SDimitry Andric private:
218a7dea167SDimitry Andric std::unique_ptr<MangleContext> Mangler;
2190b57cec5SDimitry Andric protected:
2200b57cec5SDimitry Andric ASTContext &Context;
2210b57cec5SDimitry Andric public:
ItaniumCXXABI(ASTContext & Ctx)222a7dea167SDimitry Andric ItaniumCXXABI(ASTContext &Ctx)
223a7dea167SDimitry Andric : Mangler(Ctx.createMangleContext()), Context(Ctx) {}
2240b57cec5SDimitry Andric
2250b57cec5SDimitry Andric MemberPointerInfo
getMemberPointerInfo(const MemberPointerType * MPT) const2260b57cec5SDimitry Andric getMemberPointerInfo(const MemberPointerType *MPT) const override {
2270b57cec5SDimitry Andric const TargetInfo &Target = Context.getTargetInfo();
228*bdd1243dSDimitry Andric TargetInfo::IntType PtrDiff = Target.getPtrDiffType(LangAS::Default);
2290b57cec5SDimitry Andric MemberPointerInfo MPI;
2300b57cec5SDimitry Andric MPI.Width = Target.getTypeWidth(PtrDiff);
2310b57cec5SDimitry Andric MPI.Align = Target.getTypeAlign(PtrDiff);
2320b57cec5SDimitry Andric MPI.HasPadding = false;
2330b57cec5SDimitry Andric if (MPT->isMemberFunctionPointer())
2340b57cec5SDimitry Andric MPI.Width *= 2;
2350b57cec5SDimitry Andric return MPI;
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric
getDefaultMethodCallConv(bool isVariadic) const2380b57cec5SDimitry Andric CallingConv getDefaultMethodCallConv(bool isVariadic) const override {
2390b57cec5SDimitry Andric const llvm::Triple &T = Context.getTargetInfo().getTriple();
2400b57cec5SDimitry Andric if (!isVariadic && T.isWindowsGNUEnvironment() &&
2410b57cec5SDimitry Andric T.getArch() == llvm::Triple::x86)
2420b57cec5SDimitry Andric return CC_X86ThisCall;
2430b57cec5SDimitry Andric return Context.getTargetInfo().getDefaultCallingConv();
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric
2460b57cec5SDimitry Andric // We cheat and just check that the class has a vtable pointer, and that it's
2470b57cec5SDimitry Andric // only big enough to have a vtable pointer and nothing more (or less).
isNearlyEmpty(const CXXRecordDecl * RD) const2480b57cec5SDimitry Andric bool isNearlyEmpty(const CXXRecordDecl *RD) const override {
2490b57cec5SDimitry Andric
2500b57cec5SDimitry Andric // Check that the class has a vtable pointer.
2510b57cec5SDimitry Andric if (!RD->isDynamicClass())
2520b57cec5SDimitry Andric return false;
2530b57cec5SDimitry Andric
2540b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
255*bdd1243dSDimitry Andric CharUnits PointerSize = Context.toCharUnitsFromBits(
256*bdd1243dSDimitry Andric Context.getTargetInfo().getPointerWidth(LangAS::Default));
2570b57cec5SDimitry Andric return Layout.getNonVirtualSize() == PointerSize;
2580b57cec5SDimitry Andric }
2590b57cec5SDimitry Andric
2600b57cec5SDimitry Andric const CXXConstructorDecl *
getCopyConstructorForExceptionObject(CXXRecordDecl * RD)2610b57cec5SDimitry Andric getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
2620b57cec5SDimitry Andric return nullptr;
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric
addCopyConstructorForExceptionObject(CXXRecordDecl * RD,CXXConstructorDecl * CD)2650b57cec5SDimitry Andric void addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
2660b57cec5SDimitry Andric CXXConstructorDecl *CD) override {}
2670b57cec5SDimitry Andric
addTypedefNameForUnnamedTagDecl(TagDecl * TD,TypedefNameDecl * DD)2680b57cec5SDimitry Andric void addTypedefNameForUnnamedTagDecl(TagDecl *TD,
2690b57cec5SDimitry Andric TypedefNameDecl *DD) override {}
2700b57cec5SDimitry Andric
getTypedefNameForUnnamedTagDecl(const TagDecl * TD)2710b57cec5SDimitry Andric TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override {
2720b57cec5SDimitry Andric return nullptr;
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric
addDeclaratorForUnnamedTagDecl(TagDecl * TD,DeclaratorDecl * DD)2750b57cec5SDimitry Andric void addDeclaratorForUnnamedTagDecl(TagDecl *TD,
2760b57cec5SDimitry Andric DeclaratorDecl *DD) override {}
2770b57cec5SDimitry Andric
getDeclaratorForUnnamedTagDecl(const TagDecl * TD)2780b57cec5SDimitry Andric DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override {
2790b57cec5SDimitry Andric return nullptr;
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric
2820b57cec5SDimitry Andric std::unique_ptr<MangleNumberingContext>
createMangleNumberingContext() const2830b57cec5SDimitry Andric createMangleNumberingContext() const override {
284349cc55cSDimitry Andric if (Context.getLangOpts().isSYCL())
285349cc55cSDimitry Andric return std::make_unique<ItaniumSYCLNumberingContext>(
286349cc55cSDimitry Andric cast<ItaniumMangleContext>(Mangler.get()));
287a7dea167SDimitry Andric return std::make_unique<ItaniumNumberingContext>(
288a7dea167SDimitry Andric cast<ItaniumMangleContext>(Mangler.get()));
2890b57cec5SDimitry Andric }
2900b57cec5SDimitry Andric };
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric
CreateItaniumCXXABI(ASTContext & Ctx)2930b57cec5SDimitry Andric CXXABI *clang::CreateItaniumCXXABI(ASTContext &Ctx) {
2940b57cec5SDimitry Andric return new ItaniumCXXABI(Ctx);
2950b57cec5SDimitry Andric }
296d409305fSDimitry Andric
297d409305fSDimitry Andric std::unique_ptr<MangleNumberingContext>
createItaniumNumberingContext(MangleContext * Mangler)298d409305fSDimitry Andric clang::createItaniumNumberingContext(MangleContext *Mangler) {
299d409305fSDimitry Andric return std::make_unique<ItaniumNumberingContext>(
300d409305fSDimitry Andric cast<ItaniumMangleContext>(Mangler));
301d409305fSDimitry Andric }
302