18#include "llvm/Support/AMDGPUAddrSpace.h"
19#include "llvm/Support/AtomicOrdering.h"
29 unsigned OrderIndex, ScopeIndex;
31 const auto *FD =
SemaRef.getCurFunctionDecl(
true);
32 assert(FD &&
"AMDGPU builtins should not be used outside of a function");
33 llvm::StringMap<bool> CallerFeatureMap;
39 case AMDGPU::BI__builtin_amdgcn_raw_ptr_buffer_load_lds:
40 case AMDGPU::BI__builtin_amdgcn_struct_ptr_buffer_load_lds:
41 case AMDGPU::BI__builtin_amdgcn_load_to_lds:
42 case AMDGPU::BI__builtin_amdgcn_global_load_lds: {
43 constexpr const int SizeIdx = 2;
47 SemaRef.VerifyIntegerConstantExpression(ArgExpr, &Size);
49 switch (Size.getSExtValue()) {
61 Diag(ArgExpr->
getExprLoc(), diag::err_amdgcn_load_lds_size_invalid_value)
63 Diag(ArgExpr->
getExprLoc(), diag::note_amdgcn_load_lds_size_valid_value)
68 case AMDGPU::BI__builtin_amdgcn_get_fpenv:
69 case AMDGPU::BI__builtin_amdgcn_set_fpenv:
71 case AMDGPU::BI__builtin_amdgcn_atomic_inc32:
72 case AMDGPU::BI__builtin_amdgcn_atomic_inc64:
73 case AMDGPU::BI__builtin_amdgcn_atomic_dec32:
74 case AMDGPU::BI__builtin_amdgcn_atomic_dec64:
78 case AMDGPU::BI__builtin_amdgcn_fence:
82 case AMDGPU::BI__builtin_amdgcn_mov_dpp:
84 case AMDGPU::BI__builtin_amdgcn_mov_dpp8:
86 case AMDGPU::BI__builtin_amdgcn_update_dpp:
88 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f16_fp8:
89 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_bf16_fp8:
90 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f16_bf8:
91 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_bf16_bf8:
92 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f16_fp4:
93 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_bf16_fp4:
94 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f32_fp8:
95 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f32_bf8:
96 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f32_fp4:
97 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f16_fp6:
98 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_bf16_fp6:
99 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f16_bf6:
100 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_bf16_bf6:
101 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f32_fp6:
102 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f32_bf6:
103 return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 7);
104 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_load_32x4B:
105 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_load_16x8B:
106 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_load_8x16B:
108 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_store_32x4B:
109 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_store_16x8B:
110 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_store_8x16B:
117 auto ArgExpr = Arg.
get();
121 return Diag(ArgExpr->getExprLoc(), diag::err_typecheck_expect_int)
122 << ArgExpr->getType();
123 auto Ord = ArgResult.
Val.
getInt().getZExtValue();
127 if (!llvm::isValidAtomicOrderingCABI(Ord))
128 return Diag(ArgExpr->getBeginLoc(),
129 diag::warn_atomic_op_has_invalid_memory_order)
130 << 0 << ArgExpr->getSourceRange();
131 switch (
static_cast<llvm::AtomicOrderingCABI
>(Ord)) {
132 case llvm::AtomicOrderingCABI::relaxed:
133 case llvm::AtomicOrderingCABI::consume:
134 if (BuiltinID == AMDGPU::BI__builtin_amdgcn_fence)
135 return Diag(ArgExpr->getBeginLoc(),
136 diag::warn_atomic_op_has_invalid_memory_order)
137 << 0 << ArgExpr->getSourceRange();
139 case llvm::AtomicOrderingCABI::acquire:
140 case llvm::AtomicOrderingCABI::release:
141 case llvm::AtomicOrderingCABI::acq_rel:
142 case llvm::AtomicOrderingCABI::seq_cst:
146 Arg = TheCall->
getArg(ScopeIndex);
150 if (!ArgExpr->EvaluateAsConstantExpr(ArgResult1,
getASTContext()))
151 return Diag(ArgExpr->getExprLoc(), diag::err_expr_not_string_literal)
152 << ArgExpr->getType();
164 if (AS != llvm::AMDGPUAS::FLAT_ADDRESS &&
165 AS != llvm::AMDGPUAS::GLOBAL_ADDRESS) {
172 Expr *AtomicOrdArg = TheCall->
getArg(IsStore ? 2 : 1);
175 llvm_unreachable(
"Intrinsic requires imm for atomic ordering argument!");
177 llvm::AtomicOrderingCABI(AtomicOrdArgRes.
Val.
getInt().getZExtValue());
181 if (!llvm::isValidAtomicOrderingCABI((
unsigned)Ord) ||
182 (Ord == llvm::AtomicOrderingCABI::acq_rel) ||
183 Ord == (IsStore ? llvm::AtomicOrderingCABI::acquire
184 : llvm::AtomicOrderingCABI::release)) {
186 diag::warn_atomic_op_has_invalid_memory_order)
202 unsigned NumDataArgs) {
203 assert(NumDataArgs <= 2);
204 if (
SemaRef.checkArgCountRange(TheCall, NumArgs, NumArgs))
208 for (
unsigned I = 0; I != NumDataArgs; ++I) {
209 Args[I] = TheCall->
getArg(I);
210 ArgTys[I] = Args[I]->
getType();
212 if (!ArgTys[I]->isArithmeticType() || ArgTys[I]->isAnyComplexType()) {
213 SemaRef.Diag(Args[I]->getBeginLoc(),
214 diag::err_typecheck_cond_expect_int_float)
222 if (
getASTContext().hasSameUnqualifiedType(ArgTys[0], ArgTys[1]))
225 if (((ArgTys[0]->isUnsignedIntegerType() &&
226 ArgTys[1]->isSignedIntegerType()) ||
227 (ArgTys[0]->isSignedIntegerType() &&
228 ArgTys[1]->isUnsignedIntegerType())) &&
233 SemaRef.Diag(Args[1]->getBeginLoc(),
234 diag::err_typecheck_call_different_arg_types)
235 << ArgTys[0] << ArgTys[1];
241 const AMDGPUFlatWorkGroupSizeAttr &
Attr) {
255 if (
Min == 0 &&
Max != 0) {
269AMDGPUFlatWorkGroupSizeAttr *
273 AMDGPUFlatWorkGroupSizeAttr TmpAttr(Context, CI, MinExpr, MaxExpr);
277 return ::new (Context)
278 AMDGPUFlatWorkGroupSizeAttr(Context, CI, MinExpr, MaxExpr);
298 const AMDGPUWavesPerEUAttr &
Attr) {
316 if (
Min == 0 &&
Max != 0) {
330AMDGPUWavesPerEUAttr *
334 AMDGPUWavesPerEUAttr TmpAttr(Context, CI, MinExpr, MaxExpr);
339 return ::new (Context) AMDGPUWavesPerEUAttr(Context, CI, MinExpr, MaxExpr);
359 uint32_t NumSGPR = 0;
361 if (!
SemaRef.checkUInt32Argument(AL, NumSGPRExpr, NumSGPR))
369 uint32_t NumVGPR = 0;
371 if (!
SemaRef.checkUInt32Argument(AL, NumVGPRExpr, NumVGPR))
381 const AMDGPUMaxNumWorkGroupsAttr &
Attr) {
394 Expr *Exprs[3] = {XExpr, YExpr, ZExpr};
395 for (
int i = 0; i < 3; i++) {
414 AMDGPUMaxNumWorkGroupsAttr TmpAttr(Context, CI, XExpr, YExpr, ZExpr);
420 return ::new (Context)
421 AMDGPUMaxNumWorkGroupsAttr(Context, CI, XExpr, YExpr, ZExpr);
This file declares semantic analysis functions specific to AMDGPU.
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 ...
void getFunctionFeatureMap(llvm::StringMap< bool > &FeatureMap, const FunctionDecl *) const
unsigned getTargetAddressSpace(LangAS AS) const
Attr - This represents one attribute.
SourceLocation getLocation() const
SourceLocation getLoc() const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
SourceLocation getBeginLoc() const
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Decl - This represents one declaration (or definition), e.g.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isValueDependent() const
Determines whether the value of this expression depends on.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
ParsedAttr - Represents a syntactic attribute.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
Expr * getArgAsExpr(unsigned Arg) const
bool checkAtLeastNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has at least as many args as Num.
bool checkAtMostNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has at most as many args as Num.
A (possibly-)qualified type.
void handleAMDGPUMaxNumWorkGroupsAttr(Decl *D, const ParsedAttr &AL)
void addAMDGPUFlatWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
addAMDGPUFlatWorkGroupSizeAttr - Adds an amdgpu_flat_work_group_size attribute to a particular declar...
bool checkCoopAtomicFunctionCall(CallExpr *TheCall, bool IsStore)
void handleAMDGPUFlatWorkGroupSizeAttr(Decl *D, const ParsedAttr &AL)
void handleAMDGPUNumSGPRAttr(Decl *D, const ParsedAttr &AL)
AMDGPUMaxNumWorkGroupsAttr * CreateAMDGPUMaxNumWorkGroupsAttr(const AttributeCommonInfo &CI, Expr *XExpr, Expr *YExpr, Expr *ZExpr)
Create an AMDGPUMaxNumWorkGroupsAttr attribute.
AMDGPUWavesPerEUAttr * CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
Create an AMDGPUWavesPerEUAttr attribute.
void handleAMDGPUNumVGPRAttr(Decl *D, const ParsedAttr &AL)
AMDGPUFlatWorkGroupSizeAttr * CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
Create an AMDGPUWavesPerEUAttr attribute.
bool checkMovDPPFunctionCall(CallExpr *TheCall, unsigned NumArgs, unsigned NumDataArgs)
void handleAMDGPUWavesPerEUAttr(Decl *D, const ParsedAttr &AL)
bool CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
addAMDGPUWavePersEUAttr - Adds an amdgpu_waves_per_eu attribute to a particular declaration.
void addAMDGPUMaxNumWorkGroupsAttr(Decl *D, const AttributeCommonInfo &CI, Expr *XExpr, Expr *YExpr, Expr *ZExpr)
addAMDGPUMaxNumWorkGroupsAttr - Adds an amdgpu_max_num_work_groups attribute to a particular declarat...
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
ASTContext & getASTContext() const
Sema - This implements semantic analysis and AST building for C.
bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TypeSourceInfo *T, UnexpandedParameterPackContext UPPC)
If the given type contains an unexpanded parameter pack, diagnose the error.
bool checkUInt32Argument(const AttrInfo &AI, const Expr *Expr, uint32_t &Val, unsigned Idx=UINT_MAX, bool StrictlyUnsigned=false)
If Expr is a valid integer constant, get the value of the integer expression and return success or fa...
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool evaluateRequiredTargetFeatures(llvm::StringRef RequiredFatures, const llvm::StringMap< bool > &TargetFetureMap)
Returns true if the required target features of a builtin function are enabled.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
static bool checkAMDGPUMaxNumWorkGroupsArguments(Sema &S, Expr *XExpr, Expr *YExpr, Expr *ZExpr, const AMDGPUMaxNumWorkGroupsAttr &Attr)
static bool checkAMDGPUFlatWorkGroupSizeArguments(Sema &S, Expr *MinExpr, Expr *MaxExpr, const AMDGPUFlatWorkGroupSizeAttr &Attr)
ActionResult< Expr * > ExprResult
static bool checkAMDGPUWavesPerEUArguments(Sema &S, Expr *MinExpr, Expr *MaxExpr, const AMDGPUWavesPerEUAttr &Attr)
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.