1//===--- TargetCXXABI.h - C++ ABI Target Configuration ----------*- C++ -*-===//
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/// \file
10/// Defines the TargetCXXABI class, which abstracts details of the
11/// C++ ABI that we're targeting.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_BASIC_TARGETCXXABI_H
16#define LLVM_CLANG_BASIC_TARGETCXXABI_H
17
18#include <map>
19
20#include "clang/Basic/LLVM.h"
21#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/Triple.h"
23#include "llvm/Support/ErrorHandling.h"
24
25namespace clang {
26
27/// The basic abstraction for the target C++ ABI.
28class TargetCXXABI {
29public:
30 /// The basic C++ ABI kind.
31 enum Kind {
32#define CXXABI(Name, Str) Name,
33#include "TargetCXXABI.def"
34 };
35
36private:
37 // Right now, this class is passed around as a cheap value type.
38 // If you add more members, especially non-POD members, please
39 // audit the users to pass it by reference instead.
40 Kind TheKind;
41
42 static const auto &getABIMap() {
43 static llvm::StringMap<Kind> ABIMap = {
44#define CXXABI(Name, Str) {Str, Name},
45#include "TargetCXXABI.def"
46 };
47 return ABIMap;
48 }
49
50 static const auto &getSpellingMap() {
51 static std::map<Kind, std::string> SpellingMap = {
52#define CXXABI(Name, Str) {Name, Str},
53#include "TargetCXXABI.def"
54 };
55 return SpellingMap;
56 }
57
58public:
59 static Kind getKind(StringRef Name) { return getABIMap().lookup(Name); }
60 static const auto &getSpelling(Kind ABIKind) {
61 return getSpellingMap().find(ABIKind)->second;
62 }
63 static bool isABI(StringRef Name) {
64 return getABIMap().find(Name) != getABIMap().end();
65 }
66
67 /// A bogus initialization of the platform ABI.
68 TargetCXXABI() : TheKind(GenericItanium) {}
69
70 TargetCXXABI(Kind kind) : TheKind(kind) {}
71
72 void set(Kind kind) {
73 TheKind = kind;
74 }
75
76 Kind getKind() const { return TheKind; }
77
78 // Check that the kind provided by the fc++-abi flag is supported on this
79 // target. Users who want to experiment using different ABIs on specific
80 // platforms can change this freely, but this function should be conservative
81 // enough such that not all ABIs are allowed on all platforms. For example, we
82 // probably don't want to allow usage of an ARM ABI on an x86 architecture.
83 static bool isSupportedCXXABI(const llvm::Triple &T, Kind Kind) {
84 switch (Kind) {
85 case GenericARM:
86 return T.isARM() || T.isAArch64();
87
88 case iOS:
89 case WatchOS:
90 case AppleARM64:
91 return T.isOSDarwin();
92
93 case Fuchsia:
94 return T.isOSFuchsia();
95
96 case GenericAArch64:
97 return T.isAArch64();
98
99 case GenericMIPS:
100 return T.isMIPS();
101
102 case WebAssembly:
103 return T.isWasm();
104
105 case XL:
106 return T.isOSAIX();
107
108 case GenericItanium:
109 return true;
110
111 case Microsoft:
112 return T.isKnownWindowsMSVCEnvironment();
113 }
114 llvm_unreachable("invalid CXXABI kind");
115 };
116
117 /// Does this ABI generally fall into the Itanium family of ABIs?
118 bool isItaniumFamily() const {
119 switch (getKind()) {
120#define CXXABI(Name, Str)
121#define ITANIUM_CXXABI(Name, Str) case Name:
122#include "TargetCXXABI.def"
123 return true;
124
125 default:
126 return false;
127 }
128 llvm_unreachable("bad ABI kind");
129 }
130
131 /// Is this ABI an MSVC-compatible ABI?
132 bool isMicrosoft() const {
133 switch (getKind()) {
134#define CXXABI(Name, Str)
135#define MICROSOFT_CXXABI(Name, Str) case Name:
136#include "TargetCXXABI.def"
137 return true;
138
139 default:
140 return false;
141 }
142 llvm_unreachable("bad ABI kind");
143 }
144
145 /// Are member functions differently aligned?
146 ///
147 /// Many Itanium-style C++ ABIs require member functions to be aligned, so
148 /// that a pointer to such a function is guaranteed to have a zero in the
149 /// least significant bit, so that pointers to member functions can use that
150 /// bit to distinguish between virtual and non-virtual functions. However,
151 /// some Itanium-style C++ ABIs differentiate between virtual and non-virtual
152 /// functions via other means, and consequently don't require that member
153 /// functions be aligned.
154 bool areMemberFunctionsAligned() const {
155 switch (getKind()) {
156 case WebAssembly:
157 // WebAssembly doesn't require any special alignment for member functions.
158 return false;
159 case AppleARM64:
160 case Fuchsia:
161 case GenericARM:
162 case GenericAArch64:
163 case GenericMIPS:
164 // TODO: ARM-style pointers to member functions put the discriminator in
165 // the this adjustment, so they don't require functions to have any
166 // special alignment and could therefore also return false.
167 case GenericItanium:
168 case iOS:
169 case WatchOS:
170 case Microsoft:
171 case XL:
172 return true;
173 }
174 llvm_unreachable("bad ABI kind");
175 }
176
177 /// Are arguments to a call destroyed left to right in the callee?
178 /// This is a fundamental language change, since it implies that objects
179 /// passed by value do *not* live to the end of the full expression.
180 /// Temporaries passed to a function taking a const reference live to the end
181 /// of the full expression as usual. Both the caller and the callee must
182 /// have access to the destructor, while only the caller needs the
183 /// destructor if this is false.
184 bool areArgsDestroyedLeftToRightInCallee() const {
185 return isMicrosoft();
186 }
187
188 /// Does this ABI have different entrypoints for complete-object
189 /// and base-subobject constructors?
190 bool hasConstructorVariants() const {
191 return isItaniumFamily();
192 }
193
194 /// Does this ABI allow virtual bases to be primary base classes?
195 bool hasPrimaryVBases() const {
196 return isItaniumFamily();
197 }
198
199 /// Does this ABI use key functions? If so, class data such as the
200 /// vtable is emitted with strong linkage by the TU containing the key
201 /// function.
202 bool hasKeyFunctions() const {
203 return isItaniumFamily();
204 }
205
206 /// Can an out-of-line inline function serve as a key function?
207 ///
208 /// This flag is only useful in ABIs where type data (for example,
209 /// vtables and type_info objects) are emitted only after processing
210 /// the definition of a special "key" virtual function. (This is safe
211 /// because the ODR requires that every virtual function be defined
212 /// somewhere in a program.) This usually permits such data to be
213 /// emitted in only a single object file, as opposed to redundantly
214 /// in every object file that requires it.
215 ///
216 /// One simple and common definition of "key function" is the first
217 /// virtual function in the class definition which is not defined there.
218 /// This rule works very well when that function has a non-inline
219 /// definition in some non-header file. Unfortunately, when that
220 /// function is defined inline, this rule requires the type data
221 /// to be emitted weakly, as if there were no key function.
222 ///
223 /// The ARM ABI observes that the ODR provides an additional guarantee:
224 /// a virtual function is always ODR-used, so if it is defined inline,
225 /// that definition must appear in every translation unit that defines
226 /// the class. Therefore, there is no reason to allow such functions
227 /// to serve as key functions.
228 ///
229 /// Because this changes the rules for emitting type data,
230 /// it can cause type data to be emitted with both weak and strong
231 /// linkage, which is not allowed on all platforms. Therefore,
232 /// exploiting this observation requires an ABI break and cannot be
233 /// done on a generic Itanium platform.
234 bool canKeyFunctionBeInline() const {
235 switch (getKind()) {
236 case AppleARM64:
237 case Fuchsia:
238 case GenericARM:
239 case WebAssembly:
240 case WatchOS:
241 return false;
242
243 case GenericAArch64:
244 case GenericItanium:
245 case iOS: // old iOS compilers did not follow this rule
246 case Microsoft:
247 case GenericMIPS:
248 case XL:
249 return true;
250 }
251 llvm_unreachable("bad ABI kind");
252 }
253
254 /// When is record layout allowed to allocate objects in the tail
255 /// padding of a base class?
256 ///
257 /// This decision cannot be changed without breaking platform ABI
258 /// compatibility. In ISO C++98, tail padding reuse was only permitted for
259 /// non-POD base classes, but that restriction was removed retroactively by
260 /// DR 43, and tail padding reuse is always permitted in all de facto C++
261 /// language modes. However, many platforms use a variant of the old C++98
262 /// rule for compatibility.
263 enum TailPaddingUseRules {
264 /// The tail-padding of a base class is always theoretically
265 /// available, even if it's POD.
266 AlwaysUseTailPadding,
267
268 /// Only allocate objects in the tail padding of a base class if
269 /// the base class is not POD according to the rules of C++ TR1.
270 UseTailPaddingUnlessPOD03,
271
272 /// Only allocate objects in the tail padding of a base class if
273 /// the base class is not POD according to the rules of C++11.
274 UseTailPaddingUnlessPOD11
275 };
276 TailPaddingUseRules getTailPaddingUseRules() const {
277 switch (getKind()) {
278 // To preserve binary compatibility, the generic Itanium ABI has
279 // permanently locked the definition of POD to the rules of C++ TR1,
280 // and that trickles down to derived ABIs.
281 case GenericItanium:
282 case GenericAArch64:
283 case GenericARM:
284 case iOS:
285 case GenericMIPS:
286 case XL:
287 return UseTailPaddingUnlessPOD03;
288
289 // AppleARM64 and WebAssembly use the C++11 POD rules. They do not honor
290 // the Itanium exception about classes with over-large bitfields.
291 case AppleARM64:
292 case Fuchsia:
293 case WebAssembly:
294 case WatchOS:
295 return UseTailPaddingUnlessPOD11;
296
297 // MSVC always allocates fields in the tail-padding of a base class
298 // subobject, even if they're POD.
299 case Microsoft:
300 return AlwaysUseTailPadding;
301 }
302 llvm_unreachable("bad ABI kind");
303 }
304
305 friend bool operator==(const TargetCXXABI &left, const TargetCXXABI &right) {
306 return left.getKind() == right.getKind();
307 }
308
309 friend bool operator!=(const TargetCXXABI &left, const TargetCXXABI &right) {
310 return !(left == right);
311 }
312};
313
314} // end namespace clang
315
316#endif
317