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