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/iterator.h" |
28 | #include <optional> |
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> static bool isDenseMapKeyEmpty(T V) { |
79 | return llvm::DenseMapInfo<T>::isEqual( |
80 | V, llvm::DenseMapInfo<T>::getEmptyKey()); |
81 | } |
82 | template <typename T> static bool isDenseMapKeyTombstone(T V) { |
83 | return llvm::DenseMapInfo<T>::isEqual( |
84 | V, llvm::DenseMapInfo<T>::getTombstoneKey()); |
85 | } |
86 | |
87 | template <typename T> |
88 | static std::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 std::nullopt; |
100 | } |
101 | |
102 | template<> |
103 | struct DenseMapInfo<DecompositionDeclName> { |
104 | using ArrayInfo = llvm::DenseMapInfo<ArrayRef<const BindingDecl*>>; |
105 | static DecompositionDeclName getEmptyKey() { |
106 | return {.Bindings: ArrayInfo::getEmptyKey()}; |
107 | } |
108 | static DecompositionDeclName getTombstoneKey() { |
109 | return {.Bindings: ArrayInfo::getTombstoneKey()}; |
110 | } |
111 | static unsigned getHashValue(DecompositionDeclName Key) { |
112 | assert(!isEqual(Key, getEmptyKey()) && !isEqual(Key, getTombstoneKey())); |
113 | return llvm::hash_combine_range(R&: Key); |
114 | } |
115 | static bool isEqual(DecompositionDeclName LHS, DecompositionDeclName RHS) { |
116 | if (std::optional<bool> Result = |
117 | areDenseMapKeysEqualSpecialValues(LHS: LHS.Bindings, RHS: RHS.Bindings)) |
118 | return *Result; |
119 | |
120 | return LHS.Bindings.size() == RHS.Bindings.size() && |
121 | std::equal(first1: LHS.begin(), last1: LHS.end(), first2: 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>(Val: VD)) { |
166 | DecompositionDeclName Name{.Bindings: 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: *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(Key: CallOperator, Args&: 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(Val: 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(AddrSpace: LangAS::Default); |
228 | MemberPointerInfo MPI; |
229 | MPI.Width = Target.getTypeWidth(T: PtrDiff); |
230 | MPI.Align = Target.getTypeAlign(T: 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 = Context.toCharUnitsFromBits( |
255 | BitSize: Context.getTargetInfo().getPointerWidth(AddrSpace: LangAS::Default)); |
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 | args: cast<ItaniumMangleContext>(Val: Mangler.get())); |
286 | return std::make_unique<ItaniumNumberingContext>( |
287 | args: cast<ItaniumMangleContext>(Val: 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 | args: cast<ItaniumMangleContext>(Val: Mangler)); |
300 | } |
301 |
Definitions
- findAnonymousUnionVarDeclName
- DecompositionDeclName
- Iterator
- Iterator
- operator*
- begin
- end
- isDenseMapKeyEmpty
- isDenseMapKeyTombstone
- areDenseMapKeysEqualSpecialValues
- DenseMapInfo
- getEmptyKey
- getTombstoneKey
- getHashValue
- isEqual
- ItaniumNumberingContext
- ItaniumNumberingContext
- getManglingNumber
- getManglingNumber
- getStaticLocalNumber
- getManglingNumber
- getManglingNumber
- ItaniumSYCLNumberingContext
- ItaniumSYCLNumberingContext
- getManglingNumber
- getDeviceManglingNumber
- ItaniumCXXABI
- ItaniumCXXABI
- getMemberPointerInfo
- getDefaultMethodCallConv
- isNearlyEmpty
- getCopyConstructorForExceptionObject
- addCopyConstructorForExceptionObject
- addTypedefNameForUnnamedTagDecl
- getTypedefNameForUnnamedTagDecl
- addDeclaratorForUnnamedTagDecl
- getDeclaratorForUnnamedTagDecl
- createMangleNumberingContext
- CreateItaniumCXXABI
Improve your Profiling and Debugging skills
Find out more