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 {.Bindings: ArrayInfo::getEmptyKey()}; |
108 | } |
109 | static DecompositionDeclName getTombstoneKey() { |
110 | return {.Bindings: ArrayInfo::getTombstoneKey()}; |
111 | } |
112 | static unsigned getHashValue(DecompositionDeclName Key) { |
113 | assert(!isEqual(Key, getEmptyKey()) && !isEqual(Key, getTombstoneKey())); |
114 | return llvm::hash_combine_range(first: Key.begin(), last: Key.end()); |
115 | } |
116 | static bool isEqual(DecompositionDeclName LHS, DecompositionDeclName RHS) { |
117 | if (std::optional<bool> Result = |
118 | areDenseMapKeysEqualSpecialValues(LHS: LHS.Bindings, RHS: 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>(Val: VD)) { |
167 | DecompositionDeclName Name{.Bindings: 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: *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(Key: CallOperator, Args&: 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(Val: 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(AddrSpace: LangAS::Default); |
229 | MemberPointerInfo MPI; |
230 | MPI.Width = Target.getTypeWidth(T: PtrDiff); |
231 | MPI.Align = Target.getTypeAlign(T: 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(D: RD); |
255 | CharUnits PointerSize = Context.toCharUnitsFromBits( |
256 | BitSize: Context.getTargetInfo().getPointerWidth(AddrSpace: 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 | args: cast<ItaniumMangleContext>(Val: Mangler.get())); |
287 | return std::make_unique<ItaniumNumberingContext>( |
288 | args: cast<ItaniumMangleContext>(Val: 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 | args: cast<ItaniumMangleContext>(Val: Mangler)); |
301 | } |
302 | |