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/Mangle.h" 23 #include "clang/AST/MangleNumberingContext.h" 24 #include "clang/AST/RecordLayout.h" 25 #include "clang/AST/Type.h" 26 #include "clang/Basic/TargetInfo.h" 27 #include "llvm/ADT/FoldingSet.h" 28 #include "llvm/ADT/iterator.h" 29 30 using namespace clang; 31 32 namespace { 33 34 /// According to Itanium C++ ABI 5.1.2: 35 /// the name of an anonymous union is considered to be 36 /// the name of the first named data member found by a pre-order, 37 /// depth-first, declaration-order walk of the data members of 38 /// the anonymous union. 39 /// If there is no such data member (i.e., if all of the data members 40 /// in the union are unnamed), then there is no way for a program to 41 /// refer to the anonymous union, and there is therefore no need to mangle its name. 42 /// 43 /// Returns the name of anonymous union VarDecl or nullptr if it is not found. 44 static const IdentifierInfo *findAnonymousUnionVarDeclName(const VarDecl& VD) { 45 const RecordType *RT = VD.getType()->getAs<RecordType>(); 46 assert(RT && "type of VarDecl is expected to be RecordType."); 47 assert(RT->getDecl()->isUnion() && "RecordType is expected to be a union."); 48 if (const FieldDecl *FD = RT->getDecl()->findFirstNamedDataMember()) { 49 return FD->getIdentifier(); 50 } 51 52 return nullptr; 53 } 54 55 /// The name of a decomposition declaration. 56 struct DecompositionDeclName { 57 using BindingArray = ArrayRef<const BindingDecl*>; 58 59 /// Representative example of a set of bindings with these names. 60 BindingArray Bindings; 61 62 /// Iterators over the sequence of identifiers in the name. 63 struct Iterator 64 : llvm::iterator_adaptor_base<Iterator, BindingArray::const_iterator, 65 std::random_access_iterator_tag, 66 const IdentifierInfo *> { 67 Iterator(BindingArray::const_iterator It) : iterator_adaptor_base(It) {} 68 const IdentifierInfo *operator*() const { 69 return (*this->I)->getIdentifier(); 70 } 71 }; 72 Iterator begin() const { return Iterator(Bindings.begin()); } 73 Iterator end() const { return Iterator(Bindings.end()); } 74 }; 75 } 76 77 namespace llvm { 78 template<typename T> bool isDenseMapKeyEmpty(T V) { 79 return llvm::DenseMapInfo<T>::isEqual( 80 V, llvm::DenseMapInfo<T>::getEmptyKey()); 81 } 82 template<typename T> bool isDenseMapKeyTombstone(T V) { 83 return llvm::DenseMapInfo<T>::isEqual( 84 V, llvm::DenseMapInfo<T>::getTombstoneKey()); 85 } 86 87 template<typename T> 88 Optional<bool> areDenseMapKeysEqualSpecialValues(T LHS, T RHS) { 89 bool LHSEmpty = isDenseMapKeyEmpty(LHS); 90 bool RHSEmpty = isDenseMapKeyEmpty(RHS); 91 if (LHSEmpty || RHSEmpty) 92 return LHSEmpty && RHSEmpty; 93 94 bool LHSTombstone = isDenseMapKeyTombstone(LHS); 95 bool RHSTombstone = isDenseMapKeyTombstone(RHS); 96 if (LHSTombstone || RHSTombstone) 97 return LHSTombstone && RHSTombstone; 98 99 return None; 100 } 101 102 template<> 103 struct DenseMapInfo<DecompositionDeclName> { 104 using ArrayInfo = llvm::DenseMapInfo<ArrayRef<const BindingDecl*>>; 105 static DecompositionDeclName getEmptyKey() { 106 return {ArrayInfo::getEmptyKey()}; 107 } 108 static DecompositionDeclName getTombstoneKey() { 109 return {ArrayInfo::getTombstoneKey()}; 110 } 111 static unsigned getHashValue(DecompositionDeclName Key) { 112 assert(!isEqual(Key, getEmptyKey()) && !isEqual(Key, getTombstoneKey())); 113 return llvm::hash_combine_range(Key.begin(), Key.end()); 114 } 115 static bool isEqual(DecompositionDeclName LHS, DecompositionDeclName RHS) { 116 if (Optional<bool> Result = areDenseMapKeysEqualSpecialValues( 117 LHS.Bindings, RHS.Bindings)) 118 return *Result; 119 120 return LHS.Bindings.size() == RHS.Bindings.size() && 121 std::equal(LHS.begin(), LHS.end(), RHS.begin()); 122 } 123 }; 124 } 125 126 namespace { 127 128 /// Keeps track of the mangled names of lambda expressions and block 129 /// literals within a particular context. 130 class ItaniumNumberingContext : public MangleNumberingContext { 131 ItaniumMangleContext *Mangler; 132 llvm::StringMap<unsigned> LambdaManglingNumbers; 133 unsigned BlockManglingNumber = 0; 134 llvm::DenseMap<const IdentifierInfo *, unsigned> VarManglingNumbers; 135 llvm::DenseMap<const IdentifierInfo *, unsigned> TagManglingNumbers; 136 llvm::DenseMap<DecompositionDeclName, unsigned> 137 DecompsitionDeclManglingNumbers; 138 139 public: 140 ItaniumNumberingContext(ItaniumMangleContext *Mangler) : Mangler(Mangler) {} 141 142 unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override { 143 const CXXRecordDecl *Lambda = CallOperator->getParent(); 144 assert(Lambda->isLambda()); 145 146 // Computation of the <lambda-sig> is non-trivial and subtle. Rather than 147 // duplicating it here, just mangle the <lambda-sig> directly. 148 llvm::SmallString<128> LambdaSig; 149 llvm::raw_svector_ostream Out(LambdaSig); 150 Mangler->mangleLambdaSig(Lambda, Out); 151 152 return ++LambdaManglingNumbers[LambdaSig]; 153 } 154 155 unsigned getManglingNumber(const BlockDecl *BD) override { 156 return ++BlockManglingNumber; 157 } 158 159 unsigned getStaticLocalNumber(const VarDecl *VD) override { 160 return 0; 161 } 162 163 /// Variable decls are numbered by identifier. 164 unsigned getManglingNumber(const VarDecl *VD, unsigned) override { 165 if (auto *DD = dyn_cast<DecompositionDecl>(VD)) { 166 DecompositionDeclName Name{DD->bindings()}; 167 return ++DecompsitionDeclManglingNumbers[Name]; 168 } 169 170 const IdentifierInfo *Identifier = VD->getIdentifier(); 171 if (!Identifier) { 172 // VarDecl without an identifier represents an anonymous union 173 // declaration. 174 Identifier = findAnonymousUnionVarDeclName(*VD); 175 } 176 return ++VarManglingNumbers[Identifier]; 177 } 178 179 unsigned getManglingNumber(const TagDecl *TD, unsigned) override { 180 return ++TagManglingNumbers[TD->getIdentifier()]; 181 } 182 }; 183 184 // A version of this for SYCL that makes sure that 'device' mangling context 185 // matches the lambda mangling number, so that __builtin_sycl_unique_stable_name 186 // can be consistently generated between a MS and Itanium host by just referring 187 // to the device mangling number. 188 class ItaniumSYCLNumberingContext : public ItaniumNumberingContext { 189 llvm::DenseMap<const CXXMethodDecl *, unsigned> ManglingNumbers; 190 using ManglingItr = decltype(ManglingNumbers)::iterator; 191 192 public: 193 ItaniumSYCLNumberingContext(ItaniumMangleContext *Mangler) 194 : ItaniumNumberingContext(Mangler) {} 195 196 unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override { 197 unsigned Number = ItaniumNumberingContext::getManglingNumber(CallOperator); 198 std::pair<ManglingItr, bool> emplace_result = 199 ManglingNumbers.try_emplace(CallOperator, Number); 200 (void)emplace_result; 201 assert(emplace_result.second && "Lambda number set multiple times?"); 202 return Number; 203 } 204 205 using ItaniumNumberingContext::getManglingNumber; 206 207 unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override { 208 ManglingItr Itr = ManglingNumbers.find(CallOperator); 209 assert(Itr != ManglingNumbers.end() && "Lambda not yet mangled?"); 210 211 return Itr->second; 212 } 213 }; 214 215 class ItaniumCXXABI : public CXXABI { 216 private: 217 std::unique_ptr<MangleContext> Mangler; 218 protected: 219 ASTContext &Context; 220 public: 221 ItaniumCXXABI(ASTContext &Ctx) 222 : Mangler(Ctx.createMangleContext()), Context(Ctx) {} 223 224 MemberPointerInfo 225 getMemberPointerInfo(const MemberPointerType *MPT) const override { 226 const TargetInfo &Target = Context.getTargetInfo(); 227 TargetInfo::IntType PtrDiff = Target.getPtrDiffType(0); 228 MemberPointerInfo MPI; 229 MPI.Width = Target.getTypeWidth(PtrDiff); 230 MPI.Align = Target.getTypeAlign(PtrDiff); 231 MPI.HasPadding = false; 232 if (MPT->isMemberFunctionPointer()) 233 MPI.Width *= 2; 234 return MPI; 235 } 236 237 CallingConv getDefaultMethodCallConv(bool isVariadic) const override { 238 const llvm::Triple &T = Context.getTargetInfo().getTriple(); 239 if (!isVariadic && T.isWindowsGNUEnvironment() && 240 T.getArch() == llvm::Triple::x86) 241 return CC_X86ThisCall; 242 return Context.getTargetInfo().getDefaultCallingConv(); 243 } 244 245 // We cheat and just check that the class has a vtable pointer, and that it's 246 // only big enough to have a vtable pointer and nothing more (or less). 247 bool isNearlyEmpty(const CXXRecordDecl *RD) const override { 248 249 // Check that the class has a vtable pointer. 250 if (!RD->isDynamicClass()) 251 return false; 252 253 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); 254 CharUnits PointerSize = 255 Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); 256 return Layout.getNonVirtualSize() == PointerSize; 257 } 258 259 const CXXConstructorDecl * 260 getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override { 261 return nullptr; 262 } 263 264 void addCopyConstructorForExceptionObject(CXXRecordDecl *RD, 265 CXXConstructorDecl *CD) override {} 266 267 void addTypedefNameForUnnamedTagDecl(TagDecl *TD, 268 TypedefNameDecl *DD) override {} 269 270 TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override { 271 return nullptr; 272 } 273 274 void addDeclaratorForUnnamedTagDecl(TagDecl *TD, 275 DeclaratorDecl *DD) override {} 276 277 DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override { 278 return nullptr; 279 } 280 281 std::unique_ptr<MangleNumberingContext> 282 createMangleNumberingContext() const override { 283 if (Context.getLangOpts().isSYCL()) 284 return std::make_unique<ItaniumSYCLNumberingContext>( 285 cast<ItaniumMangleContext>(Mangler.get())); 286 return std::make_unique<ItaniumNumberingContext>( 287 cast<ItaniumMangleContext>(Mangler.get())); 288 } 289 }; 290 } 291 292 CXXABI *clang::CreateItaniumCXXABI(ASTContext &Ctx) { 293 return new ItaniumCXXABI(Ctx); 294 } 295 296 std::unique_ptr<MangleNumberingContext> 297 clang::createItaniumNumberingContext(MangleContext *Mangler) { 298 return std::make_unique<ItaniumNumberingContext>( 299 cast<ItaniumMangleContext>(Mangler)); 300 } 301