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"
11
12using namespace clang;
13using namespace clang::CIRGen;
14
16 const auto *rd = t->getAsRecordDecl();
17 if (!rd)
18 return false;
19 if (rd->hasFlexibleArrayMember())
20 return false;
21
22 if (const auto *cxxrd = dyn_cast<CXXRecordDecl>(rd)) {
23 // A vtable pointer is neither a base nor a field, so clang's predicate
24 // calls a polymorphic class empty and leans on its callers rejecting one as
25 // non-trivially-copyable beforehand. This answer is read off the record
26 // type without that precondition, so rule it out here instead.
27 if (cxxrd->isDynamicClass())
28 return false;
29
30 for (const auto &i : cxxrd->bases())
31 if (!isEmptyRecordForABI(context, i.getType()))
32 return false;
33 }
34
35 for (const auto *i : rd->fields())
36 if (!isEmptyFieldForABI(context, i))
37 return false;
38 return true;
39}
40
42 const FieldDecl *fd) {
43 // A zero-width bit-field holds no bits, so it holds no data. Any other
44 // unnamed bit-field is real storage that the x86-64 classifier gives the
45 // eightbyte classes of a named bit-field, so it does hold data.
46 //
47 // FIXME: this needs an ABI compatibility check. Clang used to ignore every
48 // unnamed bit-field here, and the older compatibility levels have to keep
49 // that answer once there is a switch to ask.
50 if (fd->isUnnamedBitField())
51 return fd->isZeroLengthBitField();
52
53 QualType ft = fd->getType();
54
55 // An array of empty records is empty, and a zero-length array always is.
56 bool wasArray = false;
57 while (const ConstantArrayType *at = context.getAsConstantArrayType(ft)) {
58 if (at->isZeroSize())
59 return true;
60 ft = at->getElementType();
61 wasArray = true;
62 }
63
64 const auto *rt = ft->getAsCanonical<RecordType>();
65 if (!rt)
66 return false;
67
68 // A C++ record field is never empty under the Itanium ABI unless
69 // [[no_unique_address]] makes it so, and that exception covers a record
70 // rather than an array of them.
71 if (isa<CXXRecordDecl>(rt->getDecl()) &&
72 (wasArray || !fd->hasAttr<NoUniqueAddressAttr>()))
73 return false;
74
75 return isEmptyRecordForABI(context, ft);
76}
77
78namespace {
79
80class AMDGPUABIInfo : public ABIInfo {
81public:
82 AMDGPUABIInfo(CIRGenTypes &cgt) : ABIInfo(cgt) {}
83};
84
85class AMDGPUTargetCIRGenInfo : public TargetCIRGenInfo {
86public:
87 AMDGPUTargetCIRGenInfo(CIRGenTypes &cgt)
88 : TargetCIRGenInfo(std::make_unique<AMDGPUABIInfo>(cgt)) {}
89
90 bool supportsLibCall() const override { return false; }
91
92 cir::CallingConv getDeviceKernelCallingConv() const override {
93 return cir::CallingConv::AMDGPUKernel;
94 }
95
96 void setCUDAKernelCallingConvention(const FunctionType *&ft) const override {
97 ft = getABIInfo().cgt.getASTContext().adjustFunctionType(
99 }
100
101 void setTargetAttributes(const clang::Decl *decl, mlir::Operation *global,
102 CIRGenModule &cgm) const override {
103 if (auto func = mlir::dyn_cast<cir::FuncOp>(global)) {
105 decl,
106 func.getGlobalVisibility() == cir::VisibilityKind::Hidden)) {
107 func.setGlobalVisibility(cir::VisibilityKind::Protected);
108 func.setDSOLocal(true);
109 }
111 } else if (auto gv = mlir::dyn_cast<cir::GlobalOp>(global)) {
113 decl, gv.getGlobalVisibility() == cir::VisibilityKind::Hidden)) {
114 gv.setGlobalVisibility(cir::VisibilityKind::Protected);
115 gv.setDSOLocal(true);
116 }
117 }
118 }
119
121 getGlobalVarAddressSpace(CIRGenModule &cgm,
122 const clang::VarDecl *decl) const override {
123 using clang::LangAS;
124 assert(!cgm.getLangOpts().OpenCL &&
125 !(cgm.getLangOpts().CUDA && cgm.getLangOpts().CUDAIsDevice) &&
126 "Address space agnostic languages only");
127 LangAS defaultGlobalAS = LangAS::opencl_global;
128 if (!decl)
129 return defaultGlobalAS;
130
131 LangAS addrSpace = decl->getType().getAddressSpace();
132 if (addrSpace != LangAS::Default)
133 return addrSpace;
134
135 // Only promote to address space 4 if VarDecl has constant initialization.
136 if (decl->getType().isConstantStorage(cgm.getASTContext(), false, false) &&
137 decl->hasConstantInitialization())
138 return LangAS::opencl_constant;
139
140 return defaultGlobalAS;
141 }
142
143 mlir::ptr::MemorySpaceAttrInterface
144 getCIRAllocaAddressSpace() const override {
145 return cir::LangAddressSpaceAttr::get(
146 &getABIInfo().cgt.getMLIRContext(),
147 cir::LangAddressSpace::OffloadPrivate);
148 }
149};
150
151} // namespace
152
153namespace {
154
155class X8664ABIInfo : public ABIInfo {
156public:
157 X8664ABIInfo(CIRGenTypes &cgt) : ABIInfo(cgt) {}
158};
159
160class X8664TargetCIRGenInfo : public TargetCIRGenInfo {
161public:
162 X8664TargetCIRGenInfo(CIRGenTypes &cgt)
163 : TargetCIRGenInfo(std::make_unique<X8664ABIInfo>(cgt)) {}
164};
165} // namespace
166
167std::unique_ptr<TargetCIRGenInfo>
169 return std::make_unique<AMDGPUTargetCIRGenInfo>(cgt);
170}
171
172std::unique_ptr<TargetCIRGenInfo>
174 return std::make_unique<X8664TargetCIRGenInfo>(cgt);
175}
176
177ABIInfo::~ABIInfo() noexcept = default;
178
180 const FunctionNoProtoType *fnType) const {
181 // The following conventions are known to require this to be false:
182 // x86_stdcall
183 // MIPS
184 // For everything else, we just prefer false unless we opt out.
185 return false;
186}
187
189 // Device kernels are entered through a runtime API, not called as normal
190 // sub-functions, so a modified C calling convention is used.
191 assert(getABIInfo().cgt.getASTContext().getLangOpts().OpenCL &&
192 "Kernel calling convention only defined for OpenCL");
193 return cir::CallingConv::C;
194}
195
197 cir::PointerType ptrTy,
198 QualType qt,
199 mlir::Location loc) const {
200 return cgm.getBuilder().getNullPtr(ptrTy, loc);
201}
202
205 const clang::VarDecl *d) const {
206 assert(!cgm.getLangOpts().OpenCL &&
207 !(cgm.getLangOpts().CUDA && cgm.getLangOpts().CUDAIsDevice) &&
208 "Address space agnostic languages only");
209 return d ? d->getType().getAddressSpace() : LangAS::Default;
210}
Provides definitions for the various language-specific address spaces.
static void setCUDAKernelCallingConvention(CanQualType &funcTy, CIRGenModule &cgm, const FunctionDecl *fd)
Set calling convention for CUDA/HIP kernel.
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
const ConstantArrayType * getAsConstantArrayType(QualType T) const
This class organizes the cross-function state that is used while generating CIR code.
clang::ASTContext & getASTContext() const
CIRGenBuilderTy & getBuilder()
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
virtual mlir::Value getNullPointer(CIRGenModule &cgm, cir::PointerType ptrTy, QualType qt, mlir::Location loc) const
Get the CIR value of a null pointer of type ptrTy, where qt is the source pointer type.
const ABIInfo & getABIInfo() const
Returns ABI info helper for the target.
Definition TargetInfo.h:55
TargetCIRGenInfo(std::unique_ptr< ABIInfo > info)
Definition TargetInfo.h:50
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 cir::CallingConv getDeviceKernelCallingConv() const
Returns the calling convention used for device kernels on this target.
virtual bool isNoProtoCallVariadic(const FunctionNoProtoType *fnType) const
Determine whether a call to an unprototyped functions under the given calling convention should use t...
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3858
bool hasAttr() const
Definition DeclBase.h:585
Represents a member of a struct/union/class.
Definition Decl.h:3299
bool isUnnamedBitField() const
Determines whether this is an unnamed bitfield.
Definition Decl.h:3405
bool isZeroLengthBitField() const
Is this a zero-length bit-field?
Definition Decl.cpp:4834
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:4994
ExtInfo withCallingConv(CallingConv cc) const
Definition TypeBase.h:4835
ExtInfo getExtInfo() const
Definition TypeBase.h:4968
A (possibly-)qualified type.
Definition TypeBase.h:938
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8572
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:3002
QualType getType() const
Definition Decl.h:724
Represents a variable declaration or definition.
Definition Decl.h:933
void setAMDGPUTargetFunctionAttributes(const clang::Decl *decl, cir::FuncOp func, CIRGenModule &cgm)
Set AMDGPU-specific function attributes for HIP kernels.
Definition AMDGPU.cpp:214
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 a zero-width bit-field or an...
std::unique_ptr< TargetCIRGenInfo > createX8664TargetCIRGenInfo(CIRGenTypes &cgt)
bool requiresAMDGPUProtectedVisibility(const Decl *D, bool HasHiddenVisibility)
Returns whether D must be given protected visibility on AMDGPU.
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.
@ CC_DeviceKernel
Definition Specifiers.h:295