1 //===------- ItaniumCXXABI.cpp - AST support for the Itanium C++ ABI ------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This provides C++ AST support targeting the Itanium C++ ABI, which is 10 // documented at: 11 // http://www.codesourcery.com/public/cxx-abi/abi.html 12 // http://www.codesourcery.com/public/cxx-abi/abi-eh.html 13 // 14 // It also supports the closely-related ARM C++ ABI, documented at: 15 // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf 16 // 17 //===----------------------------------------------------------------------===// 18 19 #include "CXXABI.h" 20 #include "clang/AST/ASTContext.h" 21 #include "clang/AST/DeclCXX.h" 22 #include "clang/AST/MangleNumberingContext.h" 23 #include "clang/AST/RecordLayout.h" 24 #include "clang/AST/Type.h" 25 #include "clang/Basic/TargetInfo.h" 26 #include "llvm/ADT/iterator.h" 27 28 using namespace clang; 29 30 namespace { 31 32 /// According to Itanium C++ ABI 5.1.2: 33 /// the name of an anonymous union is considered to be 34 /// the name of the first named data member found by a pre-order, 35 /// depth-first, declaration-order walk of the data members of 36 /// the anonymous union. 37 /// If there is no such data member (i.e., if all of the data members 38 /// in the union are unnamed), then there is no way for a program to 39 /// refer to the anonymous union, and there is therefore no need to mangle its name. 40 /// 41 /// Returns the name of anonymous union VarDecl or nullptr if it is not found. 42 static const IdentifierInfo *findAnonymousUnionVarDeclName(const VarDecl& VD) { 43 const RecordType *RT = VD.getType()->getAs<RecordType>(); 44 assert(RT && "type of VarDecl is expected to be RecordType."); 45 assert(RT->getDecl()->isUnion() && "RecordType is expected to be a union."); 46 if (const FieldDecl *FD = RT->getDecl()->findFirstNamedDataMember()) { 47 return FD->getIdentifier(); 48 } 49 50 return nullptr; 51 } 52 53 /// The name of a decomposition declaration. 54 struct DecompositionDeclName { 55 using BindingArray = ArrayRef<const BindingDecl*>; 56 57 /// Representative example of a set of bindings with these names. 58 BindingArray Bindings; 59 60 /// Iterators over the sequence of identifiers in the name. 61 struct Iterator 62 : llvm::iterator_adaptor_base<Iterator, BindingArray::const_iterator, 63 std::random_access_iterator_tag, 64 const IdentifierInfo *> { 65 Iterator(BindingArray::const_iterator It) : iterator_adaptor_base(It) {} 66 const IdentifierInfo *operator*() const { 67 return (*this->I)->getIdentifier(); 68 } 69 }; 70 Iterator begin() const { return Iterator(Bindings.begin()); } 71 Iterator end() const { return Iterator(Bindings.end()); } 72 }; 73 } 74 75 namespace llvm { 76 template<> 77 struct DenseMapInfo<DecompositionDeclName> { 78 using ArrayInfo = llvm::DenseMapInfo<ArrayRef<const BindingDecl*>>; 79 using IdentInfo = llvm::DenseMapInfo<const IdentifierInfo*>; 80 static DecompositionDeclName getEmptyKey() { 81 return {ArrayInfo::getEmptyKey()}; 82 } 83 static DecompositionDeclName getTombstoneKey() { 84 return {ArrayInfo::getTombstoneKey()}; 85 } 86 static unsigned getHashValue(DecompositionDeclName Key) { 87 assert(!isEqual(Key, getEmptyKey()) && !isEqual(Key, getTombstoneKey())); 88 return llvm::hash_combine_range(Key.begin(), Key.end()); 89 } 90 static bool isEqual(DecompositionDeclName LHS, DecompositionDeclName RHS) { 91 if (ArrayInfo::isEqual(LHS.Bindings, ArrayInfo::getEmptyKey())) 92 return ArrayInfo::isEqual(RHS.Bindings, ArrayInfo::getEmptyKey()); 93 if (ArrayInfo::isEqual(LHS.Bindings, ArrayInfo::getTombstoneKey())) 94 return ArrayInfo::isEqual(RHS.Bindings, ArrayInfo::getTombstoneKey()); 95 return LHS.Bindings.size() == RHS.Bindings.size() && 96 std::equal(LHS.begin(), LHS.end(), RHS.begin()); 97 } 98 }; 99 } 100 101 namespace { 102 103 /// Keeps track of the mangled names of lambda expressions and block 104 /// literals within a particular context. 105 class ItaniumNumberingContext : public MangleNumberingContext { 106 llvm::DenseMap<const Type *, unsigned> ManglingNumbers; 107 llvm::DenseMap<const IdentifierInfo *, unsigned> VarManglingNumbers; 108 llvm::DenseMap<const IdentifierInfo *, unsigned> TagManglingNumbers; 109 llvm::DenseMap<DecompositionDeclName, unsigned> 110 DecompsitionDeclManglingNumbers; 111 112 public: 113 unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override { 114 const FunctionProtoType *Proto = 115 CallOperator->getType()->getAs<FunctionProtoType>(); 116 ASTContext &Context = CallOperator->getASTContext(); 117 118 FunctionProtoType::ExtProtoInfo EPI; 119 EPI.Variadic = Proto->isVariadic(); 120 QualType Key = 121 Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI); 122 Key = Context.getCanonicalType(Key); 123 return ++ManglingNumbers[Key->castAs<FunctionProtoType>()]; 124 } 125 126 unsigned getManglingNumber(const BlockDecl *BD) override { 127 const Type *Ty = nullptr; 128 return ++ManglingNumbers[Ty]; 129 } 130 131 unsigned getStaticLocalNumber(const VarDecl *VD) override { 132 return 0; 133 } 134 135 /// Variable decls are numbered by identifier. 136 unsigned getManglingNumber(const VarDecl *VD, unsigned) override { 137 if (auto *DD = dyn_cast<DecompositionDecl>(VD)) { 138 DecompositionDeclName Name{DD->bindings()}; 139 return ++DecompsitionDeclManglingNumbers[Name]; 140 } 141 142 const IdentifierInfo *Identifier = VD->getIdentifier(); 143 if (!Identifier) { 144 // VarDecl without an identifier represents an anonymous union 145 // declaration. 146 Identifier = findAnonymousUnionVarDeclName(*VD); 147 } 148 return ++VarManglingNumbers[Identifier]; 149 } 150 151 unsigned getManglingNumber(const TagDecl *TD, unsigned) override { 152 return ++TagManglingNumbers[TD->getIdentifier()]; 153 } 154 }; 155 156 class ItaniumCXXABI : public CXXABI { 157 protected: 158 ASTContext &Context; 159 public: 160 ItaniumCXXABI(ASTContext &Ctx) : Context(Ctx) { } 161 162 MemberPointerInfo 163 getMemberPointerInfo(const MemberPointerType *MPT) const override { 164 const TargetInfo &Target = Context.getTargetInfo(); 165 TargetInfo::IntType PtrDiff = Target.getPtrDiffType(0); 166 MemberPointerInfo MPI; 167 MPI.Width = Target.getTypeWidth(PtrDiff); 168 MPI.Align = Target.getTypeAlign(PtrDiff); 169 MPI.HasPadding = false; 170 if (MPT->isMemberFunctionPointer()) 171 MPI.Width *= 2; 172 return MPI; 173 } 174 175 CallingConv getDefaultMethodCallConv(bool isVariadic) const override { 176 const llvm::Triple &T = Context.getTargetInfo().getTriple(); 177 if (!isVariadic && T.isWindowsGNUEnvironment() && 178 T.getArch() == llvm::Triple::x86) 179 return CC_X86ThisCall; 180 return Context.getTargetInfo().getDefaultCallingConv(); 181 } 182 183 // We cheat and just check that the class has a vtable pointer, and that it's 184 // only big enough to have a vtable pointer and nothing more (or less). 185 bool isNearlyEmpty(const CXXRecordDecl *RD) const override { 186 187 // Check that the class has a vtable pointer. 188 if (!RD->isDynamicClass()) 189 return false; 190 191 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); 192 CharUnits PointerSize = 193 Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); 194 return Layout.getNonVirtualSize() == PointerSize; 195 } 196 197 const CXXConstructorDecl * 198 getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override { 199 return nullptr; 200 } 201 202 void addCopyConstructorForExceptionObject(CXXRecordDecl *RD, 203 CXXConstructorDecl *CD) override {} 204 205 void addTypedefNameForUnnamedTagDecl(TagDecl *TD, 206 TypedefNameDecl *DD) override {} 207 208 TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override { 209 return nullptr; 210 } 211 212 void addDeclaratorForUnnamedTagDecl(TagDecl *TD, 213 DeclaratorDecl *DD) override {} 214 215 DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override { 216 return nullptr; 217 } 218 219 std::unique_ptr<MangleNumberingContext> 220 createMangleNumberingContext() const override { 221 return llvm::make_unique<ItaniumNumberingContext>(); 222 } 223 }; 224 } 225 226 CXXABI *clang::CreateItaniumCXXABI(ASTContext &Ctx) { 227 return new ItaniumCXXABI(Ctx); 228 } 229