clang 24.0.0git
CodeGenUtils.cpp
Go to the documentation of this file.
1//==--- CodeGenUtils.cpp - Shared Classic CodeGen/CIR CodeGen Utils--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
10#include "clang/AST/Attr.h"
11#include "clang/AST/Expr.h"
16#include "llvm/ADT/StringMap.h"
17
18namespace clang::CodeGenUtils {
19static bool
21 const CXXRecordDecl *BaseClassDecl,
22 const CXXRecordDecl *MostDerivedClassDecl) {
23 // If the destructor is trivial we don't have to check anything else.
24 if (BaseClassDecl->hasTrivialDestructor())
25 return true;
26
27 if (!BaseClassDecl->getDestructor()->hasTrivialBody())
28 return false;
29
30 // Check fields.
31 for (const auto *Field : BaseClassDecl->fields())
32 if (!fieldHasTrivialDestructorBody(Context, Field))
33 return false;
34
35 // Check non-virtual bases.
36 for (const auto &I : BaseClassDecl->bases()) {
37 if (I.isVirtual())
38 continue;
39
40 const auto *NonVirtualBase = I.getType()->castAsCXXRecordDecl();
42 MostDerivedClassDecl))
43 return false;
44 }
45
46 if (BaseClassDecl == MostDerivedClassDecl) {
47 // Check virtual bases.
48 for (const auto &I : BaseClassDecl->vbases()) {
49 const auto *VirtualBase = I.getType()->castAsCXXRecordDecl();
50 if (!hasTrivialDestructorBody(Context, VirtualBase, MostDerivedClassDecl))
51 return false;
52 }
53 }
54
55 return true;
56}
57
59 const FieldDecl *Field) {
60 QualType FieldBaseElementType = Context.getBaseElementType(Field->getType());
61
62 auto *FieldClassDecl = FieldBaseElementType->getAsCXXRecordDecl();
63 if (!FieldClassDecl)
64 return true;
65
66 // The destructor for an implicit anonymous union member is never invoked.
67 if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
68 return true;
69
70 return hasTrivialDestructorBody(Context, FieldClassDecl, FieldClassDecl);
71}
72
73/// Check whether we need to initialize any vtable pointers before calling this
74/// destructor.
76 const CXXDestructorDecl *Dtor) {
77 const CXXRecordDecl *ClassDecl = Dtor->getParent();
78 if (!ClassDecl->isDynamicClass())
79 return true;
80
81 // For a final class, the vtable pointer is known to already point to the
82 // class's vtable.
83 if (ClassDecl->isEffectivelyFinal())
84 return true;
85
86 if (!Dtor->hasTrivialBody())
87 return false;
88
89 // Check the fields.
90 for (const auto *Field : ClassDecl->fields())
91 if (!fieldHasTrivialDestructorBody(Ctx, Field))
92 return false;
93
94 return true;
95}
96bool hasUnwindExceptions(const LangOptions &LangOpts) {
97 // If exceptions are completely disabled, obviously this is false.
98 if (!LangOpts.Exceptions)
99 return false;
100
101 // If C++ exceptions are enabled, this is true.
102 if (LangOpts.CXXExceptions)
103 return true;
104
105 // If ObjC exceptions are enabled, this depends on the ABI.
106 if (LangOpts.ObjCExceptions) {
107 return LangOpts.ObjCRuntime.hasUnwindExceptions();
108 }
109
110 return true;
111}
112
114 return TargetInfo.getABI().starts_with("aapcs");
115}
117 const Type *BaseType = BaseInit->getBaseClass();
118 return BaseType->castAsCXXRecordDecl()->isDynamicClass();
119}
120
121// Emits an error if we don't have a valid set of target features for the
122// called function.
124 const LangOptions &LangOpts, const CallExpr *E,
125 const FunctionDecl *Caller,
126 const FunctionDecl *TargetDecl) {
127 // SemaChecking cannot handle these x86 builtins because they have different
128 // parameter ranges depending on the caller's TargetAttribute.
129 if (Ctx.getTargetInfo().getTriple().isX86()) {
130 unsigned BuiltinID = TargetDecl->getBuiltinID();
131 if (BuiltinID == X86::BI__builtin_ia32_cmpps ||
132 BuiltinID == X86::BI__builtin_ia32_cmpss ||
133 BuiltinID == X86::BI__builtin_ia32_cmppd ||
134 BuiltinID == X86::BI__builtin_ia32_cmpsd) {
135 llvm::StringMap<bool> TargetFeatureMap;
136 Ctx.getFunctionFeatureMap(TargetFeatureMap, Caller);
137 llvm::APSInt Result = *(E->getArg(2)->getIntegerConstantExpr(Ctx));
138 if (Result.getSExtValue() > 7 && !TargetFeatureMap.lookup("avx"))
139 Diags.Report(E->getBeginLoc(), diag::err_builtin_needs_feature)
140 << TargetDecl->getDeclName() << "avx";
141 }
142 }
143 checkTargetFeatures(Ctx, Diags, LangOpts, E->getBeginLoc(), Caller,
144 TargetDecl);
145}
146
147// Emits an error if we don't have a valid set of target features for the
148// called function.
150 const LangOptions &LangOpts, SourceLocation Loc,
151 const FunctionDecl *Caller,
152 const FunctionDecl *TargetDecl) {
153 if (!TargetDecl || !Caller)
154 return;
155
156 bool IsAlwaysInline = TargetDecl->hasAttr<AlwaysInlineAttr>();
157 bool IsFlatten = Caller->hasAttr<FlattenAttr>();
158
159 unsigned BuiltinID = TargetDecl->getBuiltinID();
160 std::string MissingFeature;
161 llvm::StringMap<bool> CallerFeatureMap;
162 Ctx.getFunctionFeatureMap(CallerFeatureMap, Caller);
163 // When compiling in HipStdPar mode we have to be conservative in rejecting
164 // target specific features in the FE, and defer the possible error to the
165 // AcceleratorCodeSelection pass, wherein iff an unsupported target builtin is
166 // referenced by an accelerator executable function, we emit an error.
167 bool IsHipStdPar = LangOpts.HIPStdPar && LangOpts.CUDAIsDevice;
168 if (BuiltinID) {
169 StringRef FeatureList(Ctx.BuiltinInfo.getRequiredFeatures(BuiltinID));
171 CallerFeatureMap) &&
172 !IsHipStdPar)
173 Diags.Report(Loc, diag::err_builtin_needs_feature)
174 << TargetDecl->getDeclName() << FeatureList;
175 } else if (!TargetDecl->isMultiVersion() &&
176 TargetDecl->hasAttr<TargetAttr>()) {
177 // Get the required features for the callee.
178 const TargetAttr *TD = TargetDecl->getAttr<TargetAttr>();
180
181 SmallVector<StringRef, 1> ReqFeatures;
182 llvm::StringMap<bool> CalleeFeatureMap;
183 Ctx.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);
184
185 for (const auto &F : ParsedAttr.Features) {
186 if (F[0] == '+' && CalleeFeatureMap.lookup(F.substr(1)))
187 ReqFeatures.push_back(StringRef(F).substr(1));
188 }
189 for (const auto &F : CalleeFeatureMap) {
190 if (F.getValue())
191 ReqFeatures.push_back(F.getKey());
192 }
193 if (!llvm::all_of(ReqFeatures,
194 [&](StringRef Feature) {
195 if (!CallerFeatureMap.lookup(Feature)) {
196 MissingFeature = Feature.str();
197 return false;
198 }
199 return true;
200 }) &&
201 !IsHipStdPar) {
202 if (IsAlwaysInline)
203 Diags.Report(Loc, diag::err_function_needs_feature)
204 << Caller->getDeclName() << TargetDecl->getDeclName()
205 << MissingFeature;
206 else if (IsFlatten)
207 Diags.Report(Loc, diag::err_flatten_function_needs_feature)
208 << Caller->getDeclName() << TargetDecl->getDeclName()
209 << MissingFeature;
210 }
211 } else if (!Caller->isMultiVersion() && Caller->hasAttr<TargetAttr>()) {
212 llvm::StringMap<bool> CalleeFeatureMap;
213 Ctx.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);
214
215 for (const auto &F : CalleeFeatureMap) {
216 if (F.getValue() &&
217 (!CallerFeatureMap.lookup(F.getKey()) ||
218 !CallerFeatureMap.find(F.getKey())->getValue()) &&
219 !IsHipStdPar) {
220 if (IsAlwaysInline)
221 Diags.Report(Loc, diag::err_function_needs_feature)
222 << Caller->getDeclName() << TargetDecl->getDeclName()
223 << F.getKey();
224 else if (IsFlatten)
225 Diags.Report(Loc, diag::err_flatten_function_needs_feature)
226 << Caller->getDeclName() << TargetDecl->getDeclName()
227 << F.getKey();
228 }
229 }
230 }
231}
232
233} // namespace clang::CodeGenUtils
Defines enum values for all the target-independent builtin functions.
Enumerates target-specific builtins in their own namespaces within namespace clang.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:239
ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD) const
Parses the target attributes passed in, and returns only the ones that are valid feature names.
Builtin::Context & BuiltinInfo
Definition ASTContext.h:848
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:965
void getFunctionFeatureMap(llvm::StringMap< bool > &FeatureMap, const FunctionDecl *) const
const char * getRequiredFeatures(unsigned ID) const
Definition Builtins.cpp:116
Represents a C++ base or member initializer.
Definition DeclCXX.h:2407
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
Definition DeclCXX.cpp:2946
Represents a C++ destructor within a class.
Definition DeclCXX.h:2907
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool isEffectivelyFinal() const
Determine whether it's impossible for a class to be derived from this class.
Definition DeclCXX.cpp:2341
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
Definition DeclCXX.h:1382
base_class_range bases()
Definition DeclCXX.h:609
base_class_range vbases()
Definition DeclCXX.h:626
bool isDynamicClass() const
Definition DeclCXX.h:575
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
Definition DeclCXX.cpp:2129
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2987
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3191
SourceLocation getBeginLoc() const
Definition Expr.h:3321
T * getAttr() const
Definition DeclBase.h:581
bool hasAttr() const
Definition DeclBase.h:585
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:232
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Represents a member of a struct/union/class.
Definition Decl.h:3295
Represents a function declaration or definition.
Definition Decl.h:2059
bool isMultiVersion() const
True if this function is considered a multiversioned function.
Definition Decl.h:2820
bool hasTrivialBody() const
Returns whether the function has a trivial body that does not require any specific codegen.
Definition Decl.cpp:3197
unsigned getBuiltinID(bool ConsiderWrapperFunctions=false) const
Returns a value indicating whether this function corresponds to a builtin function.
Definition Decl.cpp:3804
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
clang::ObjCRuntime ObjCRuntime
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:341
bool hasUnwindExceptions() const
Does this runtime use zero-cost exceptions?
ParsedAttr - Represents a syntactic attribute.
Definition ParsedAttr.h:119
A (possibly-)qualified type.
Definition TypeBase.h:938
field_range fields() const
Definition Decl.h:4663
Encodes a location in the source.
Exposes information about the current target.
Definition TargetInfo.h:226
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
virtual StringRef getABI() const
Get the ABI currently in use.
The base class of the type hierarchy.
Definition TypeBase.h:1879
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
Defines the clang::TargetInfo interface.
bool evaluateRequiredTargetFeatures(llvm::StringRef RequiredFatures, const llvm::StringMap< bool > &TargetFetureMap)
Returns true if the required target features of a builtin function are enabled.
static bool hasTrivialDestructorBody(ASTContext &Context, const CXXRecordDecl *BaseClassDecl, const CXXRecordDecl *MostDerivedClassDecl)
bool isAAPCS(const TargetInfo &TargetInfo)
Helper method to check if the underlying ABI is AAPCS.
bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit)
bool canSkipVTablePointerInitialization(ASTContext &Ctx, const CXXDestructorDecl *Dtor)
Check whether we need to initialize any vtable pointers before calling this destructor.
bool fieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field)
Check whether destructing Field has no observable behaviors, and thus can be skipped when creating a ...
bool hasUnwindExceptions(const LangOptions &LangOpts)
Determines whether the language options require us to model unwind exceptions.
void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags, const LangOptions &LangOpts, const CallExpr *E, const FunctionDecl *Caller, const FunctionDecl *TargetDecl)
Check that a call to a target-specific builtin has the required target features enabled in the caller...
@ Result
The result type of a method or function.
Definition TypeBase.h:906
Contains information gathered from parsing the contents of TargetAttr.
Definition TargetInfo.h:59