clang 22.0.0git
SemaAMDGPU.cpp
Go to the documentation of this file.
1//===------ SemaAMDGPU.cpp ------- AMDGPU target-specific routines --------===//
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// This file implements semantic analysis functions specific to AMDGPU.
10//
11//===----------------------------------------------------------------------===//
12
18#include "clang/Sema/Sema.h"
19#include "llvm/Support/AMDGPUAddrSpace.h"
20#include "llvm/Support/AtomicOrdering.h"
21#include <cstdint>
22
23namespace clang {
24
26
28 CallExpr *TheCall) {
29 // position of memory order and scope arguments in the builtin
30 unsigned OrderIndex, ScopeIndex;
31
32 const auto *FD = SemaRef.getCurFunctionDecl(/*AllowLambda=*/true);
33 assert(FD && "AMDGPU builtins should not be used outside of a function");
34 llvm::StringMap<bool> CallerFeatureMap;
35 getASTContext().getFunctionFeatureMap(CallerFeatureMap, FD);
36 bool HasGFX950Insts =
37 Builtin::evaluateRequiredTargetFeatures("gfx950-insts", CallerFeatureMap);
38
39 switch (BuiltinID) {
40 case AMDGPU::BI__builtin_amdgcn_raw_ptr_buffer_load_lds:
41 case AMDGPU::BI__builtin_amdgcn_struct_ptr_buffer_load_lds:
42 case AMDGPU::BI__builtin_amdgcn_load_to_lds:
43 case AMDGPU::BI__builtin_amdgcn_global_load_lds: {
44 constexpr const int SizeIdx = 2;
45 llvm::APSInt Size;
46 Expr *ArgExpr = TheCall->getArg(SizeIdx);
47 [[maybe_unused]] ExprResult R =
48 SemaRef.VerifyIntegerConstantExpression(ArgExpr, &Size);
49 assert(!R.isInvalid());
50 switch (Size.getSExtValue()) {
51 case 1:
52 case 2:
53 case 4:
54 return false;
55 case 12:
56 case 16: {
57 if (HasGFX950Insts)
58 return false;
59 [[fallthrough]];
60 }
61 default:
62 SemaRef.targetDiag(ArgExpr->getExprLoc(),
63 diag::err_amdgcn_load_lds_size_invalid_value)
64 << ArgExpr->getSourceRange();
65 SemaRef.targetDiag(ArgExpr->getExprLoc(),
66 diag::note_amdgcn_load_lds_size_valid_value)
67 << HasGFX950Insts << ArgExpr->getSourceRange();
68 return true;
69 }
70 }
71 case AMDGPU::BI__builtin_amdgcn_get_fpenv:
72 case AMDGPU::BI__builtin_amdgcn_set_fpenv:
73 return false;
74 case AMDGPU::BI__builtin_amdgcn_atomic_inc32:
75 case AMDGPU::BI__builtin_amdgcn_atomic_inc64:
76 case AMDGPU::BI__builtin_amdgcn_atomic_dec32:
77 case AMDGPU::BI__builtin_amdgcn_atomic_dec64:
78 OrderIndex = 2;
79 ScopeIndex = 3;
80 break;
81 case AMDGPU::BI__builtin_amdgcn_fence:
82 OrderIndex = 0;
83 ScopeIndex = 1;
84 break;
85 case AMDGPU::BI__builtin_amdgcn_mov_dpp:
86 return checkMovDPPFunctionCall(TheCall, 5, 1);
87 case AMDGPU::BI__builtin_amdgcn_mov_dpp8:
88 return checkMovDPPFunctionCall(TheCall, 2, 1);
89 case AMDGPU::BI__builtin_amdgcn_update_dpp:
90 return checkMovDPPFunctionCall(TheCall, 6, 2);
91 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f16_fp8:
92 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_bf16_fp8:
93 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f16_bf8:
94 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_bf16_bf8:
95 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f16_fp4:
96 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_bf16_fp4:
97 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f32_fp8:
98 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f32_bf8:
99 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f32_fp4:
100 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f16_fp6:
101 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_bf16_fp6:
102 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f16_bf6:
103 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_bf16_bf6:
104 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f32_fp6:
105 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f32_bf6:
106 return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 15);
107 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_load_32x4B:
108 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_load_16x8B:
109 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_load_8x16B:
110 return checkCoopAtomicFunctionCall(TheCall, /*IsStore=*/false);
111 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_store_32x4B:
112 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_store_16x8B:
113 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_store_8x16B:
114 return checkCoopAtomicFunctionCall(TheCall, /*IsStore=*/true);
115 case AMDGPU::BI__builtin_amdgcn_image_load_1d_v4f32_i32:
116 case AMDGPU::BI__builtin_amdgcn_image_load_1darray_v4f32_i32:
117 case AMDGPU::BI__builtin_amdgcn_image_load_1d_v4f16_i32:
118 case AMDGPU::BI__builtin_amdgcn_image_load_1darray_v4f16_i32:
119 case AMDGPU::BI__builtin_amdgcn_image_load_2d_f32_i32:
120 case AMDGPU::BI__builtin_amdgcn_image_load_2d_v4f32_i32:
121 case AMDGPU::BI__builtin_amdgcn_image_load_2d_v4f16_i32:
122 case AMDGPU::BI__builtin_amdgcn_image_load_2darray_f32_i32:
123 case AMDGPU::BI__builtin_amdgcn_image_load_2darray_v4f32_i32:
124 case AMDGPU::BI__builtin_amdgcn_image_load_2darray_v4f16_i32:
125 case AMDGPU::BI__builtin_amdgcn_image_load_3d_v4f32_i32:
126 case AMDGPU::BI__builtin_amdgcn_image_load_3d_v4f16_i32:
127 case AMDGPU::BI__builtin_amdgcn_image_load_cube_v4f32_i32:
128 case AMDGPU::BI__builtin_amdgcn_image_load_cube_v4f16_i32:
129 case AMDGPU::BI__builtin_amdgcn_image_load_mip_1d_v4f32_i32:
130 case AMDGPU::BI__builtin_amdgcn_image_load_mip_1d_v4f16_i32:
131 case AMDGPU::BI__builtin_amdgcn_image_load_mip_1darray_v4f32_i32:
132 case AMDGPU::BI__builtin_amdgcn_image_load_mip_1darray_v4f16_i32:
133 case AMDGPU::BI__builtin_amdgcn_image_load_mip_2d_f32_i32:
134 case AMDGPU::BI__builtin_amdgcn_image_load_mip_2d_v4f32_i32:
135 case AMDGPU::BI__builtin_amdgcn_image_load_mip_2d_v4f16_i32:
136 case AMDGPU::BI__builtin_amdgcn_image_load_mip_2darray_f32_i32:
137 case AMDGPU::BI__builtin_amdgcn_image_load_mip_2darray_v4f32_i32:
138 case AMDGPU::BI__builtin_amdgcn_image_load_mip_2darray_v4f16_i32:
139 case AMDGPU::BI__builtin_amdgcn_image_load_mip_3d_v4f32_i32:
140 case AMDGPU::BI__builtin_amdgcn_image_load_mip_3d_v4f16_i32:
141 case AMDGPU::BI__builtin_amdgcn_image_load_mip_cube_v4f32_i32:
142 case AMDGPU::BI__builtin_amdgcn_image_load_mip_cube_v4f16_i32:
143 case AMDGPU::BI__builtin_amdgcn_image_sample_1d_v4f32_f32:
144 case AMDGPU::BI__builtin_amdgcn_image_sample_1darray_v4f32_f32:
145 case AMDGPU::BI__builtin_amdgcn_image_sample_1d_v4f16_f32:
146 case AMDGPU::BI__builtin_amdgcn_image_sample_1darray_v4f16_f32:
147 case AMDGPU::BI__builtin_amdgcn_image_sample_2d_f32_f32:
148 case AMDGPU::BI__builtin_amdgcn_image_sample_2d_v4f32_f32:
149 case AMDGPU::BI__builtin_amdgcn_image_sample_2d_v4f16_f32:
150 case AMDGPU::BI__builtin_amdgcn_image_sample_2darray_f32_f32:
151 case AMDGPU::BI__builtin_amdgcn_image_sample_2darray_v4f32_f32:
152 case AMDGPU::BI__builtin_amdgcn_image_sample_2darray_v4f16_f32:
153 case AMDGPU::BI__builtin_amdgcn_image_sample_3d_v4f32_f32:
154 case AMDGPU::BI__builtin_amdgcn_image_sample_3d_v4f16_f32:
155 case AMDGPU::BI__builtin_amdgcn_image_sample_cube_v4f32_f32:
156 case AMDGPU::BI__builtin_amdgcn_image_sample_cube_v4f16_f32:
157 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_1d_v4f32_f32:
158 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_1d_v4f16_f32:
159 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_1darray_v4f32_f32:
160 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_1darray_v4f16_f32:
161 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_2d_f32_f32:
162 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_2d_v4f32_f32:
163 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_2d_v4f16_f32:
164 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_2darray_f32_f32:
165 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_2darray_v4f32_f32:
166 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_2darray_v4f16_f32:
167 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_3d_v4f32_f32:
168 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_3d_v4f16_f32:
169 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_cube_v4f32_f32:
170 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_cube_v4f16_f32:
171 case AMDGPU::BI__builtin_amdgcn_image_sample_l_1d_v4f32_f32:
172 case AMDGPU::BI__builtin_amdgcn_image_sample_l_1d_v4f16_f32:
173 case AMDGPU::BI__builtin_amdgcn_image_sample_l_1darray_v4f32_f32:
174 case AMDGPU::BI__builtin_amdgcn_image_sample_l_1darray_v4f16_f32:
175 case AMDGPU::BI__builtin_amdgcn_image_sample_l_2d_f32_f32:
176 case AMDGPU::BI__builtin_amdgcn_image_sample_l_2d_v4f16_f32:
177 case AMDGPU::BI__builtin_amdgcn_image_sample_l_2d_v4f32_f32:
178 case AMDGPU::BI__builtin_amdgcn_image_sample_l_2darray_f32_f32:
179 case AMDGPU::BI__builtin_amdgcn_image_sample_l_2darray_v4f32_f32:
180 case AMDGPU::BI__builtin_amdgcn_image_sample_l_2darray_v4f16_f32:
181 case AMDGPU::BI__builtin_amdgcn_image_sample_l_3d_v4f32_f32:
182 case AMDGPU::BI__builtin_amdgcn_image_sample_l_3d_v4f16_f32:
183 case AMDGPU::BI__builtin_amdgcn_image_sample_l_cube_v4f32_f32:
184 case AMDGPU::BI__builtin_amdgcn_image_sample_l_cube_v4f16_f32:
185 case AMDGPU::BI__builtin_amdgcn_image_sample_d_1d_v4f32_f32:
186 case AMDGPU::BI__builtin_amdgcn_image_sample_d_1d_v4f16_f32:
187 case AMDGPU::BI__builtin_amdgcn_image_sample_d_1darray_v4f32_f32:
188 case AMDGPU::BI__builtin_amdgcn_image_sample_d_1darray_v4f16_f32:
189 case AMDGPU::BI__builtin_amdgcn_image_sample_d_2d_f32_f32:
190 case AMDGPU::BI__builtin_amdgcn_image_sample_d_2d_v4f32_f32:
191 case AMDGPU::BI__builtin_amdgcn_image_sample_d_2d_v4f16_f32:
192 case AMDGPU::BI__builtin_amdgcn_image_sample_d_2darray_f32_f32:
193 case AMDGPU::BI__builtin_amdgcn_image_sample_d_2darray_v4f32_f32:
194 case AMDGPU::BI__builtin_amdgcn_image_sample_d_2darray_v4f16_f32:
195 case AMDGPU::BI__builtin_amdgcn_image_sample_d_3d_v4f32_f32:
196 case AMDGPU::BI__builtin_amdgcn_image_sample_d_3d_v4f16_f32:
197 case AMDGPU::BI__builtin_amdgcn_image_gather4_lz_2d_v4f32_f32: {
198 StringRef FeatureList(
199 getASTContext().BuiltinInfo.getRequiredFeatures(BuiltinID));
201 CallerFeatureMap)) {
202 Diag(TheCall->getBeginLoc(), diag::err_builtin_needs_feature)
203 << FD->getDeclName() << FeatureList;
204 return false;
205 }
206
207 unsigned ArgCount = TheCall->getNumArgs() - 1;
208 llvm::APSInt Result;
209
210 return (SemaRef.BuiltinConstantArg(TheCall, 0, Result)) ||
211 (SemaRef.BuiltinConstantArg(TheCall, ArgCount, Result)) ||
212 (SemaRef.BuiltinConstantArg(TheCall, (ArgCount - 1), Result));
213 }
214 case AMDGPU::BI__builtin_amdgcn_image_store_1d_v4f32_i32:
215 case AMDGPU::BI__builtin_amdgcn_image_store_1darray_v4f32_i32:
216 case AMDGPU::BI__builtin_amdgcn_image_store_1d_v4f16_i32:
217 case AMDGPU::BI__builtin_amdgcn_image_store_1darray_v4f16_i32:
218 case AMDGPU::BI__builtin_amdgcn_image_store_2d_f32_i32:
219 case AMDGPU::BI__builtin_amdgcn_image_store_2d_v4f32_i32:
220 case AMDGPU::BI__builtin_amdgcn_image_store_2d_v4f16_i32:
221 case AMDGPU::BI__builtin_amdgcn_image_store_2darray_f32_i32:
222 case AMDGPU::BI__builtin_amdgcn_image_store_2darray_v4f32_i32:
223 case AMDGPU::BI__builtin_amdgcn_image_store_2darray_v4f16_i32:
224 case AMDGPU::BI__builtin_amdgcn_image_store_3d_v4f32_i32:
225 case AMDGPU::BI__builtin_amdgcn_image_store_3d_v4f16_i32:
226 case AMDGPU::BI__builtin_amdgcn_image_store_cube_v4f32_i32:
227 case AMDGPU::BI__builtin_amdgcn_image_store_cube_v4f16_i32:
228 case AMDGPU::BI__builtin_amdgcn_image_store_mip_1d_v4f32_i32:
229 case AMDGPU::BI__builtin_amdgcn_image_store_mip_1d_v4f16_i32:
230 case AMDGPU::BI__builtin_amdgcn_image_store_mip_1darray_v4f32_i32:
231 case AMDGPU::BI__builtin_amdgcn_image_store_mip_1darray_v4f16_i32:
232 case AMDGPU::BI__builtin_amdgcn_image_store_mip_2d_f32_i32:
233 case AMDGPU::BI__builtin_amdgcn_image_store_mip_2d_v4f32_i32:
234 case AMDGPU::BI__builtin_amdgcn_image_store_mip_2d_v4f16_i32:
235 case AMDGPU::BI__builtin_amdgcn_image_store_mip_2darray_f32_i32:
236 case AMDGPU::BI__builtin_amdgcn_image_store_mip_2darray_v4f32_i32:
237 case AMDGPU::BI__builtin_amdgcn_image_store_mip_2darray_v4f16_i32:
238 case AMDGPU::BI__builtin_amdgcn_image_store_mip_3d_v4f32_i32:
239 case AMDGPU::BI__builtin_amdgcn_image_store_mip_3d_v4f16_i32:
240 case AMDGPU::BI__builtin_amdgcn_image_store_mip_cube_v4f32_i32:
241 case AMDGPU::BI__builtin_amdgcn_image_store_mip_cube_v4f16_i32: {
242 StringRef FeatureList(
243 getASTContext().BuiltinInfo.getRequiredFeatures(BuiltinID));
245 CallerFeatureMap)) {
246 Diag(TheCall->getBeginLoc(), diag::err_builtin_needs_feature)
247 << FD->getDeclName() << FeatureList;
248 return false;
249 }
250
251 unsigned ArgCount = TheCall->getNumArgs() - 1;
252 llvm::APSInt Result;
253
254 return (SemaRef.BuiltinConstantArg(TheCall, 1, Result)) ||
255 (SemaRef.BuiltinConstantArg(TheCall, ArgCount, Result)) ||
256 (SemaRef.BuiltinConstantArg(TheCall, (ArgCount - 1), Result));
257 }
258 case AMDGPU::BI__builtin_amdgcn_wmma_i32_16x16x64_iu8:
259 case AMDGPU::BI__builtin_amdgcn_swmmac_i32_16x16x128_iu8: {
260 if (BuiltinID == AMDGPU::BI__builtin_amdgcn_wmma_i32_16x16x64_iu8) {
261 if (SemaRef.checkArgCountRange(TheCall, 7, 8))
262 return true;
263 if (TheCall->getNumArgs() == 7)
264 return false;
265 } else if (BuiltinID ==
266 AMDGPU::BI__builtin_amdgcn_swmmac_i32_16x16x128_iu8) {
267 if (SemaRef.checkArgCountRange(TheCall, 8, 9))
268 return true;
269 if (TheCall->getNumArgs() == 8)
270 return false;
271 }
272 // Check if the last argument (clamp operand) is a constant and is
273 // convertible to bool.
274 Expr *ClampArg = TheCall->getArg(TheCall->getNumArgs() - 1);
275 // 1) Ensure clamp argument is a constant expression
276 llvm::APSInt ClampValue;
277 if (!SemaRef.VerifyIntegerConstantExpression(ClampArg, &ClampValue)
278 .isUsable())
279 return true;
280 // 2) Check if the argument can be converted to bool type
281 if (!SemaRef.Context.hasSameType(ClampArg->getType(),
282 SemaRef.Context.BoolTy)) {
283 // Try to convert to bool
284 QualType BoolTy = SemaRef.Context.BoolTy;
285 ExprResult ClampExpr(ClampArg);
286 SemaRef.CheckSingleAssignmentConstraints(BoolTy, ClampExpr);
287 if (ClampExpr.isInvalid())
288 return true;
289 }
290 return false;
291 }
292 default:
293 return false;
294 }
295
296 ExprResult Arg = TheCall->getArg(OrderIndex);
297 auto ArgExpr = Arg.get();
298 Expr::EvalResult ArgResult;
299
300 if (!ArgExpr->EvaluateAsInt(ArgResult, getASTContext()))
301 return Diag(ArgExpr->getExprLoc(), diag::err_typecheck_expect_int)
302 << ArgExpr->getType();
303 auto Ord = ArgResult.Val.getInt().getZExtValue();
304
305 // Check validity of memory ordering as per C11 / C++11's memory model.
306 // Only fence needs check. Atomic dec/inc allow all memory orders.
307 if (!llvm::isValidAtomicOrderingCABI(Ord))
308 return Diag(ArgExpr->getBeginLoc(),
309 diag::warn_atomic_op_has_invalid_memory_order)
310 << 0 << ArgExpr->getSourceRange();
311 switch (static_cast<llvm::AtomicOrderingCABI>(Ord)) {
312 case llvm::AtomicOrderingCABI::relaxed:
313 case llvm::AtomicOrderingCABI::consume:
314 if (BuiltinID == AMDGPU::BI__builtin_amdgcn_fence)
315 return Diag(ArgExpr->getBeginLoc(),
316 diag::warn_atomic_op_has_invalid_memory_order)
317 << 0 << ArgExpr->getSourceRange();
318 break;
319 case llvm::AtomicOrderingCABI::acquire:
320 case llvm::AtomicOrderingCABI::release:
321 case llvm::AtomicOrderingCABI::acq_rel:
322 case llvm::AtomicOrderingCABI::seq_cst:
323 break;
324 }
325
326 Arg = TheCall->getArg(ScopeIndex);
327 ArgExpr = Arg.get();
328 Expr::EvalResult ArgResult1;
329 // Check that sync scope is a constant literal
330 if (!ArgExpr->EvaluateAsConstantExpr(ArgResult1, getASTContext()))
331 return Diag(ArgExpr->getExprLoc(), diag::err_expr_not_string_literal)
332 << ArgExpr->getType();
333
334 return false;
335}
336
338 bool Fail = false;
339
340 // First argument is a global or generic pointer.
341 Expr *PtrArg = TheCall->getArg(0);
342 QualType PtrTy = PtrArg->getType()->getPointeeType();
343 unsigned AS = getASTContext().getTargetAddressSpace(PtrTy.getAddressSpace());
344 if (AS != llvm::AMDGPUAS::FLAT_ADDRESS &&
345 AS != llvm::AMDGPUAS::GLOBAL_ADDRESS) {
346 Fail = true;
347 Diag(TheCall->getBeginLoc(), diag::err_amdgcn_coop_atomic_invalid_as)
348 << PtrArg->getSourceRange();
349 }
350
351 // Check atomic ordering
352 Expr *AtomicOrdArg = TheCall->getArg(IsStore ? 2 : 1);
353 Expr::EvalResult AtomicOrdArgRes;
354 if (!AtomicOrdArg->EvaluateAsInt(AtomicOrdArgRes, getASTContext()))
355 llvm_unreachable("Intrinsic requires imm for atomic ordering argument!");
356 auto Ord =
357 llvm::AtomicOrderingCABI(AtomicOrdArgRes.Val.getInt().getZExtValue());
358
359 // Atomic ordering cannot be acq_rel in any case, acquire for stores or
360 // release for loads.
361 if (!llvm::isValidAtomicOrderingCABI((unsigned)Ord) ||
362 (Ord == llvm::AtomicOrderingCABI::acq_rel) ||
363 Ord == (IsStore ? llvm::AtomicOrderingCABI::acquire
364 : llvm::AtomicOrderingCABI::release)) {
365 return Diag(AtomicOrdArg->getBeginLoc(),
366 diag::warn_atomic_op_has_invalid_memory_order)
367 << 0 << AtomicOrdArg->getSourceRange();
368 }
369
370 // Last argument is a string literal
371 Expr *Arg = TheCall->getArg(TheCall->getNumArgs() - 1);
373 Fail = true;
374 Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal)
375 << Arg->getSourceRange();
376 }
377
378 return Fail;
379}
380
381bool SemaAMDGPU::checkMovDPPFunctionCall(CallExpr *TheCall, unsigned NumArgs,
382 unsigned NumDataArgs) {
383 assert(NumDataArgs <= 2);
384 if (SemaRef.checkArgCountRange(TheCall, NumArgs, NumArgs))
385 return true;
386 Expr *Args[2];
387 QualType ArgTys[2];
388 for (unsigned I = 0; I != NumDataArgs; ++I) {
389 Args[I] = TheCall->getArg(I);
390 ArgTys[I] = Args[I]->getType();
391 // TODO: Vectors can also be supported.
392 if (!ArgTys[I]->isArithmeticType() || ArgTys[I]->isAnyComplexType()) {
393 SemaRef.Diag(Args[I]->getBeginLoc(),
394 diag::err_typecheck_cond_expect_int_float)
395 << ArgTys[I] << Args[I]->getSourceRange();
396 return true;
397 }
398 }
399 if (NumDataArgs < 2)
400 return false;
401
402 if (getASTContext().hasSameUnqualifiedType(ArgTys[0], ArgTys[1]))
403 return false;
404
405 if (((ArgTys[0]->isUnsignedIntegerType() &&
406 ArgTys[1]->isSignedIntegerType()) ||
407 (ArgTys[0]->isSignedIntegerType() &&
408 ArgTys[1]->isUnsignedIntegerType())) &&
409 getASTContext().getTypeSize(ArgTys[0]) ==
410 getASTContext().getTypeSize(ArgTys[1]))
411 return false;
412
413 SemaRef.Diag(Args[1]->getBeginLoc(),
414 diag::err_typecheck_call_different_arg_types)
415 << ArgTys[0] << ArgTys[1];
416 return true;
417}
418
419static bool
421 const AMDGPUFlatWorkGroupSizeAttr &Attr) {
422 // Accept template arguments for now as they depend on something else.
423 // We'll get to check them when they eventually get instantiated.
424 if (MinExpr->isValueDependent() || MaxExpr->isValueDependent())
425 return false;
426
427 uint32_t Min = 0;
428 if (!S.checkUInt32Argument(Attr, MinExpr, Min, 0))
429 return true;
430
431 uint32_t Max = 0;
432 if (!S.checkUInt32Argument(Attr, MaxExpr, Max, 1))
433 return true;
434
435 if (Min == 0 && Max != 0) {
436 S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
437 << &Attr << 0;
438 return true;
439 }
440 if (Min > Max) {
441 S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
442 << &Attr << 1;
443 return true;
444 }
445
446 return false;
447}
448
449AMDGPUFlatWorkGroupSizeAttr *
451 Expr *MinExpr, Expr *MaxExpr) {
452 ASTContext &Context = getASTContext();
453 AMDGPUFlatWorkGroupSizeAttr TmpAttr(Context, CI, MinExpr, MaxExpr);
454
455 if (checkAMDGPUFlatWorkGroupSizeArguments(SemaRef, MinExpr, MaxExpr, TmpAttr))
456 return nullptr;
457 return ::new (Context)
458 AMDGPUFlatWorkGroupSizeAttr(Context, CI, MinExpr, MaxExpr);
459}
460
462 const AttributeCommonInfo &CI,
463 Expr *MinExpr, Expr *MaxExpr) {
464 if (auto *Attr = CreateAMDGPUFlatWorkGroupSizeAttr(CI, MinExpr, MaxExpr))
465 D->addAttr(Attr);
466}
467
469 const ParsedAttr &AL) {
470 Expr *MinExpr = AL.getArgAsExpr(0);
471 Expr *MaxExpr = AL.getArgAsExpr(1);
472
473 addAMDGPUFlatWorkGroupSizeAttr(D, AL, MinExpr, MaxExpr);
474}
475
476static bool checkAMDGPUWavesPerEUArguments(Sema &S, Expr *MinExpr,
477 Expr *MaxExpr,
478 const AMDGPUWavesPerEUAttr &Attr) {
479 if (S.DiagnoseUnexpandedParameterPack(MinExpr) ||
480 (MaxExpr && S.DiagnoseUnexpandedParameterPack(MaxExpr)))
481 return true;
482
483 // Accept template arguments for now as they depend on something else.
484 // We'll get to check them when they eventually get instantiated.
485 if (MinExpr->isValueDependent() || (MaxExpr && MaxExpr->isValueDependent()))
486 return false;
487
488 uint32_t Min = 0;
489 if (!S.checkUInt32Argument(Attr, MinExpr, Min, 0))
490 return true;
491
492 uint32_t Max = 0;
493 if (MaxExpr && !S.checkUInt32Argument(Attr, MaxExpr, Max, 1))
494 return true;
495
496 if (Min == 0 && Max != 0) {
497 S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
498 << &Attr << 0;
499 return true;
500 }
501 if (Max != 0 && Min > Max) {
502 S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
503 << &Attr << 1;
504 return true;
505 }
506
507 return false;
508}
509
510AMDGPUWavesPerEUAttr *
512 Expr *MinExpr, Expr *MaxExpr) {
513 ASTContext &Context = getASTContext();
514 AMDGPUWavesPerEUAttr TmpAttr(Context, CI, MinExpr, MaxExpr);
515
516 if (checkAMDGPUWavesPerEUArguments(SemaRef, MinExpr, MaxExpr, TmpAttr))
517 return nullptr;
518
519 return ::new (Context) AMDGPUWavesPerEUAttr(Context, CI, MinExpr, MaxExpr);
520}
521
523 Expr *MinExpr, Expr *MaxExpr) {
524 if (auto *Attr = CreateAMDGPUWavesPerEUAttr(CI, MinExpr, MaxExpr))
525 D->addAttr(Attr);
526}
527
530 return;
531
532 Expr *MinExpr = AL.getArgAsExpr(0);
533 Expr *MaxExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr;
534
535 addAMDGPUWavesPerEUAttr(D, AL, MinExpr, MaxExpr);
536}
537
539 uint32_t NumSGPR = 0;
540 Expr *NumSGPRExpr = AL.getArgAsExpr(0);
541 if (!SemaRef.checkUInt32Argument(AL, NumSGPRExpr, NumSGPR))
542 return;
543
544 D->addAttr(::new (getASTContext())
545 AMDGPUNumSGPRAttr(getASTContext(), AL, NumSGPR));
546}
547
549 uint32_t NumVGPR = 0;
550 Expr *NumVGPRExpr = AL.getArgAsExpr(0);
551 if (!SemaRef.checkUInt32Argument(AL, NumVGPRExpr, NumVGPR))
552 return;
553
554 D->addAttr(::new (getASTContext())
555 AMDGPUNumVGPRAttr(getASTContext(), AL, NumVGPR));
556}
557
558static bool
560 Expr *ZExpr,
561 const AMDGPUMaxNumWorkGroupsAttr &Attr) {
562 if (S.DiagnoseUnexpandedParameterPack(XExpr) ||
563 (YExpr && S.DiagnoseUnexpandedParameterPack(YExpr)) ||
564 (ZExpr && S.DiagnoseUnexpandedParameterPack(ZExpr)))
565 return true;
566
567 // Accept template arguments for now as they depend on something else.
568 // We'll get to check them when they eventually get instantiated.
569 if (XExpr->isValueDependent() || (YExpr && YExpr->isValueDependent()) ||
570 (ZExpr && ZExpr->isValueDependent()))
571 return false;
572
573 uint32_t NumWG = 0;
574 Expr *Exprs[3] = {XExpr, YExpr, ZExpr};
575 for (int i = 0; i < 3; i++) {
576 if (Exprs[i]) {
577 if (!S.checkUInt32Argument(Attr, Exprs[i], NumWG, i,
578 /*StrictlyUnsigned=*/true))
579 return true;
580 if (NumWG == 0) {
581 S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero)
582 << &Attr << Exprs[i]->getSourceRange();
583 return true;
584 }
585 }
586 }
587
588 return false;
589}
590
592 const AttributeCommonInfo &CI, Expr *XExpr, Expr *YExpr, Expr *ZExpr) {
593 ASTContext &Context = getASTContext();
594 AMDGPUMaxNumWorkGroupsAttr TmpAttr(Context, CI, XExpr, YExpr, ZExpr);
595 assert(!SemaRef.isSFINAEContext() &&
596 "Can't produce SFINAE diagnostic pointing to temporary attribute");
597
598 if (checkAMDGPUMaxNumWorkGroupsArguments(SemaRef, XExpr, YExpr, ZExpr,
599 TmpAttr))
600 return nullptr;
601
602 return ::new (Context)
603 AMDGPUMaxNumWorkGroupsAttr(Context, CI, XExpr, YExpr, ZExpr);
604}
605
607 const AttributeCommonInfo &CI,
608 Expr *XExpr, Expr *YExpr,
609 Expr *ZExpr) {
610 if (auto *Attr = CreateAMDGPUMaxNumWorkGroupsAttr(CI, XExpr, YExpr, ZExpr))
611 D->addAttr(Attr);
612}
613
615 const ParsedAttr &AL) {
616 Expr *YExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr;
617 Expr *ZExpr = (AL.getNumArgs() > 2) ? AL.getArgAsExpr(2) : nullptr;
618 addAMDGPUMaxNumWorkGroupsAttr(D, AL, AL.getArgAsExpr(0), YExpr, ZExpr);
619}
620
621} // namespace clang
This file declares semantic analysis functions specific to AMDGPU.
Enumerates target-specific builtins in their own namespaces within namespace clang.
APSInt & getInt()
Definition APValue.h:489
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
void getFunctionFeatureMap(llvm::StringMap< bool > &FeatureMap, const FunctionDecl *) const
unsigned getTargetAddressSpace(LangAS AS) const
PtrTy get() const
Definition Ownership.h:171
bool isInvalid() const
Definition Ownership.h:167
Attr - This represents one attribute.
Definition Attr.h:45
SourceLocation getLocation() const
Definition Attr.h:98
SourceLocation getLoc() const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2943
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3147
SourceLocation getBeginLoc() const
Definition Expr.h:3277
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3134
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
void addAttr(Attr *A)
This represents one expression.
Definition Expr.h:112
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.
Definition Expr.h:177
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3089
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:276
QualType getType() const
Definition Expr.h:144
ParsedAttr - Represents a syntactic attribute.
Definition ParsedAttr.h:119
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
Definition ParsedAttr.h:371
Expr * getArgAsExpr(unsigned Arg) const
Definition ParsedAttr.h:383
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.
Definition TypeBase.h:937
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...
SemaBase(Sema &S)
Definition SemaBase.cpp:7
ASTContext & getASTContext() const
Definition SemaBase.cpp:9
Sema & SemaRef
Definition SemaBase.h:40
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:855
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...
Definition Sema.h:4841
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:338
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:350
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:753
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)
Definition Address.h:330
@ Result
The result type of a method or function.
Definition TypeBase.h:905
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
Definition Ownership.h:249
static bool checkAMDGPUWavesPerEUArguments(Sema &S, Expr *MinExpr, Expr *MaxExpr, const AMDGPUWavesPerEUAttr &Attr)
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:645
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:647