clang 24.0.0git
TargetInfo.cpp
Go to the documentation of this file.
1#include "TargetInfo.h"
2#include "ABIInfo.h"
3#include "CIRGenFunction.h"
4#include "CIRGenModule.h"
5#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
10
11using namespace clang;
12using namespace clang::CIRGen;
13
15 QualType t) {
16 const auto *rd = t->getAsRecordDecl();
17 if (!rd)
18 return false;
19
20 // If this is a C++ record, check the bases first.
21 if (const CXXRecordDecl *cxxrd = dyn_cast<CXXRecordDecl>(rd)) {
22 if (cxxrd->isDynamicClass())
23 return false;
24
25 for (const auto &i : cxxrd->bases())
26 if (!isEmptyRecordForLayout(context, i.getType()))
27 return false;
28 }
29
30 for (const auto *i : rd->fields())
31 if (!isEmptyFieldForLayout(context, i))
32 return false;
33
34 return true;
35}
36
38 const FieldDecl *fd) {
39 if (fd->isZeroLengthBitField())
40 return true;
41
42 if (fd->isUnnamedBitField())
43 return false;
44
45 return isEmptyRecordForLayout(context, fd->getType());
46}
47
49 const auto *rd = t->getAsRecordDecl();
50 if (!rd)
51 return false;
52 if (rd->hasFlexibleArrayMember())
53 return false;
54
55 if (const auto *cxxrd = dyn_cast<CXXRecordDecl>(rd)) {
56 // A vtable pointer is neither a base nor a field, so clang's predicate
57 // calls a polymorphic class empty and leans on its callers rejecting one as
58 // non-trivially-copyable beforehand. This answer is read off the record
59 // type without that precondition, so rule it out here instead.
60 if (cxxrd->isDynamicClass())
61 return false;
62
63 for (const auto &i : cxxrd->bases())
64 if (!isEmptyRecordForABI(context, i.getType()))
65 return false;
66 }
67
68 for (const auto *i : rd->fields())
69 if (!isEmptyFieldForABI(context, i))
70 return false;
71 return true;
72}
73
75 const FieldDecl *fd) {
76 if (fd->isUnnamedBitField())
77 return true;
78
79 QualType ft = fd->getType();
80
81 // An array of empty records is empty, and a zero-length array always is.
82 bool wasArray = false;
83 while (const ConstantArrayType *at = context.getAsConstantArrayType(ft)) {
84 if (at->isZeroSize())
85 return true;
86 ft = at->getElementType();
87 wasArray = true;
88 }
89
90 const auto *rt = ft->getAsCanonical<RecordType>();
91 if (!rt)
92 return false;
93
94 // A C++ record field is never empty under the Itanium ABI unless
95 // [[no_unique_address]] makes it so, and that exception covers a record
96 // rather than an array of them.
97 if (isa<CXXRecordDecl>(rt->getDecl()) &&
98 (wasArray || !fd->hasAttr<NoUniqueAddressAttr>()))
99 return false;
100
101 return isEmptyRecordForABI(context, ft);
102}
103
104namespace {
105
106class AMDGPUABIInfo : public ABIInfo {
107public:
108 AMDGPUABIInfo(CIRGenTypes &cgt) : ABIInfo(cgt) {}
109};
110
111class AMDGPUTargetCIRGenInfo : public TargetCIRGenInfo {
112public:
113 AMDGPUTargetCIRGenInfo(CIRGenTypes &cgt)
114 : TargetCIRGenInfo(std::make_unique<AMDGPUABIInfo>(cgt)) {}
115
116 bool supportsLibCall() const override { return false; }
117
118 void setTargetAttributes(const clang::Decl *decl, mlir::Operation *global,
119 CIRGenModule &cgm) const override {
120 if (auto func = mlir::dyn_cast<cir::FuncOp>(global)) {
121 if (requiresAMDGPUProtectedVisibility(decl, func.getGlobalVisibility())) {
122 func.setGlobalVisibility(cir::VisibilityKind::Protected);
123 func.setDSOLocal(true);
124 }
126 } else if (auto gv = mlir::dyn_cast<cir::GlobalOp>(global)) {
127 if (requiresAMDGPUProtectedVisibility(decl, gv.getGlobalVisibility())) {
128 gv.setGlobalVisibility(cir::VisibilityKind::Protected);
129 gv.setDSOLocal(true);
130 }
131 }
132 }
133
135 getGlobalVarAddressSpace(CIRGenModule &cgm,
136 const clang::VarDecl *decl) const override {
137 using clang::LangAS;
138 assert(!cgm.getLangOpts().OpenCL &&
139 !(cgm.getLangOpts().CUDA && cgm.getLangOpts().CUDAIsDevice) &&
140 "Address space agnostic languages only");
141 LangAS defaultGlobalAS = LangAS::opencl_global;
142 if (!decl)
143 return defaultGlobalAS;
144
145 LangAS addrSpace = decl->getType().getAddressSpace();
146 if (addrSpace != LangAS::Default)
147 return addrSpace;
148
149 // Only promote to address space 4 if VarDecl has constant initialization.
150 if (decl->getType().isConstantStorage(cgm.getASTContext(), false, false) &&
151 decl->hasConstantInitialization())
152 return LangAS::opencl_constant;
153
154 return defaultGlobalAS;
155 }
156
157 mlir::ptr::MemorySpaceAttrInterface
158 getCIRAllocaAddressSpace() const override {
159 return cir::LangAddressSpaceAttr::get(
160 &getABIInfo().cgt.getMLIRContext(),
161 cir::LangAddressSpace::OffloadPrivate);
162 }
163};
164
165} // namespace
166
167namespace {
168
169class X8664ABIInfo : public ABIInfo {
170public:
171 X8664ABIInfo(CIRGenTypes &cgt) : ABIInfo(cgt) {}
172};
173
174class X8664TargetCIRGenInfo : public TargetCIRGenInfo {
175public:
176 X8664TargetCIRGenInfo(CIRGenTypes &cgt)
177 : TargetCIRGenInfo(std::make_unique<X8664ABIInfo>(cgt)) {}
178};
179} // namespace
180
181std::unique_ptr<TargetCIRGenInfo>
183 return std::make_unique<AMDGPUTargetCIRGenInfo>(cgt);
184}
185
186std::unique_ptr<TargetCIRGenInfo>
188 return std::make_unique<X8664TargetCIRGenInfo>(cgt);
189}
190
191ABIInfo::~ABIInfo() noexcept = default;
192
194 const FunctionNoProtoType *fnType) const {
195 // The following conventions are known to require this to be false:
196 // x86_stdcall
197 // MIPS
198 // For everything else, we just prefer false unless we opt out.
199 return false;
200}
201
204 const clang::VarDecl *d) const {
205 assert(!cgm.getLangOpts().OpenCL &&
206 !(cgm.getLangOpts().CUDA && cgm.getLangOpts().CUDAIsDevice) &&
207 "Address space agnostic languages only");
208 return d ? d->getType().getAddressSpace() : LangAS::Default;
209}
Provides definitions for the various language-specific address spaces.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
const ConstantArrayType * getAsConstantArrayType(QualType T) const
This class organizes the cross-function state that is used while generating CIR code.
clang::ASTContext & getASTContext() const
const clang::LangOptions & getLangOpts() const
This class organizes the cross-module state that is used while lowering AST types to CIR types.
Definition CIRGenTypes.h:51
TargetCIRGenInfo(std::unique_ptr< ABIInfo > info)
Definition TargetInfo.h:58
virtual clang::LangAS getGlobalVarAddressSpace(CIRGenModule &cgm, const clang::VarDecl *d) const
Get target favored AST address space of a global variable for languages other than OpenCL and CUDA.
virtual bool isNoProtoCallVariadic(const FunctionNoProtoType *fnType) const
Determine whether a call to an unprototyped functions under the given calling convention should use t...
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3874
bool hasAttr() const
Definition DeclBase.h:585
Represents a member of a struct/union/class.
Definition Decl.h:3294
bool isUnnamedBitField() const
Determines whether this is an unnamed bitfield.
Definition Decl.h:3400
bool isZeroLengthBitField() const
Is this a zero-length bit-field?
Definition Decl.cpp:4824
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:4999
A (possibly-)qualified type.
Definition TypeBase.h:938
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8630
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2998
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:932
void setAMDGPUTargetFunctionAttributes(const clang::Decl *decl, cir::FuncOp func, CIRGenModule &cgm)
Set AMDGPU-specific function attributes for HIP kernels.
Definition AMDGPU.cpp:228
bool isEmptyRecordForABI(const ASTContext &context, QualType t)
isEmptyRecordForABI - Return true if a structure contains only empty base classes and fields.
std::unique_ptr< TargetCIRGenInfo > createAMDGPUTargetCIRGenInfo(CIRGenTypes &cgt)
bool isEmptyFieldForABI(const ASTContext &context, const FieldDecl *fd)
isEmptyFieldForABI - Return true if the field is "empty", that is, it is an unnamed bit-field or an (...
std::unique_ptr< TargetCIRGenInfo > createX8664TargetCIRGenInfo(CIRGenTypes &cgt)
bool isEmptyFieldForLayout(const ASTContext &context, const FieldDecl *fd)
isEmptyFieldForLayout - Return true if the field is "empty", that is, either a zero-width bit-field o...
bool isEmptyRecordForLayout(const ASTContext &context, QualType t)
isEmptyRecordForLayout - Return true if a structure contains only empty base classes (per isEmptyReco...
bool requiresAMDGPUProtectedVisibility(const clang::Decl *d, cir::VisibilityKind visibility)
Check if AMDGPU protected visibility is required.
Definition AMDGPU.cpp:26
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
LangAS
Defines the address space values used by the address space qualifier of QualType.