blob: 84fccd5ef59f6245b0505bd05cd1ffa623c166b2 [file] [log] [blame]
Eli Bendersky7325e562014-09-03 15:27:03 +00001//===--- SemaCUDA.cpp - Semantic Analysis for CUDA constructs -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9/// \file
10/// \brief This file implements semantic analysis for CUDA constructs.
11///
12//===----------------------------------------------------------------------===//
13
14#include "clang/Sema/Sema.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/Decl.h"
Artem Belevich97c01c32016-02-02 22:29:48 +000017#include "clang/AST/ExprCXX.h"
Reid Klecknerbbc01782014-12-03 21:53:36 +000018#include "clang/Lex/Preprocessor.h"
Eli Bendersky7325e562014-09-03 15:27:03 +000019#include "clang/Sema/SemaDiagnostic.h"
Eli Bendersky9a220fc2014-09-29 20:38:29 +000020#include "llvm/ADT/Optional.h"
21#include "llvm/ADT/SmallVector.h"
Eli Bendersky7325e562014-09-03 15:27:03 +000022using namespace clang;
23
24ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
25 MultiExprArg ExecConfig,
26 SourceLocation GGGLoc) {
27 FunctionDecl *ConfigDecl = Context.getcudaConfigureCallDecl();
28 if (!ConfigDecl)
29 return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use)
30 << "cudaConfigureCall");
31 QualType ConfigQTy = ConfigDecl->getType();
32
33 DeclRefExpr *ConfigDR = new (Context)
34 DeclRefExpr(ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc);
35 MarkFunctionReferenced(LLLLoc, ConfigDecl);
36
37 return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr,
38 /*IsExecConfig=*/true);
39}
40
41/// IdentifyCUDATarget - Determine the CUDA compilation target for this function
42Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {
Eli Bendersky9a220fc2014-09-29 20:38:29 +000043 if (D->hasAttr<CUDAInvalidTargetAttr>())
44 return CFT_InvalidTarget;
Eli Bendersky7325e562014-09-03 15:27:03 +000045
46 if (D->hasAttr<CUDAGlobalAttr>())
47 return CFT_Global;
48
49 if (D->hasAttr<CUDADeviceAttr>()) {
50 if (D->hasAttr<CUDAHostAttr>())
51 return CFT_HostDevice;
52 return CFT_Device;
Eli Benderskyf2787a02014-09-30 17:38:34 +000053 } else if (D->hasAttr<CUDAHostAttr>()) {
54 return CFT_Host;
55 } else if (D->isImplicit()) {
56 // Some implicit declarations (like intrinsic functions) are not marked.
57 // Set the most lenient target on them for maximal flexibility.
58 return CFT_HostDevice;
Eli Bendersky7325e562014-09-03 15:27:03 +000059 }
60
61 return CFT_Host;
62}
63
Artem Belevich94a55e82015-09-22 17:22:59 +000064// * CUDA Call preference table
65//
66// F - from,
67// T - to
68// Ph - preference in host mode
69// Pd - preference in device mode
70// H - handled in (x)
71// Preferences: b-best, f-fallback, l-last resort, n-never.
72//
73// | F | T | Ph | Pd | H |
74// |----+----+----+----+-----+
75// | d | d | b | b | (b) |
76// | d | g | n | n | (a) |
77// | d | h | l | l | (e) |
78// | d | hd | f | f | (c) |
79// | g | d | b | b | (b) |
80// | g | g | n | n | (a) |
81// | g | h | l | l | (e) |
82// | g | hd | f | f | (c) |
83// | h | d | l | l | (e) |
84// | h | g | b | b | (b) |
85// | h | h | b | b | (b) |
86// | h | hd | f | f | (c) |
87// | hd | d | l | f | (d) |
88// | hd | g | f | n |(d/a)|
89// | hd | h | f | l | (d) |
90// | hd | hd | b | b | (b) |
91
92Sema::CUDAFunctionPreference
93Sema::IdentifyCUDAPreference(const FunctionDecl *Caller,
94 const FunctionDecl *Callee) {
95 assert(getLangOpts().CUDATargetOverloads &&
96 "Should not be called w/o enabled target overloads.");
97
98 assert(Callee && "Callee must be valid.");
99 CUDAFunctionTarget CalleeTarget = IdentifyCUDATarget(Callee);
100 CUDAFunctionTarget CallerTarget =
101 (Caller != nullptr) ? IdentifyCUDATarget(Caller) : Sema::CFT_Host;
102
103 // If one of the targets is invalid, the check always fails, no matter what
104 // the other target is.
105 if (CallerTarget == CFT_InvalidTarget || CalleeTarget == CFT_InvalidTarget)
106 return CFP_Never;
107
108 // (a) Can't call global from some contexts until we support CUDA's
109 // dynamic parallelism.
110 if (CalleeTarget == CFT_Global &&
111 (CallerTarget == CFT_Global || CallerTarget == CFT_Device ||
112 (CallerTarget == CFT_HostDevice && getLangOpts().CUDAIsDevice)))
113 return CFP_Never;
114
115 // (b) Best case scenarios
116 if (CalleeTarget == CallerTarget ||
117 (CallerTarget == CFT_Host && CalleeTarget == CFT_Global) ||
118 (CallerTarget == CFT_Global && CalleeTarget == CFT_Device))
119 return CFP_Best;
120
121 // (c) Calling HostDevice is OK as a fallback that works for everyone.
122 if (CalleeTarget == CFT_HostDevice)
123 return CFP_Fallback;
124
125 // Figure out what should be returned 'last resort' cases. Normally
126 // those would not be allowed, but we'll consider them if
127 // CUDADisableTargetCallChecks is true.
128 CUDAFunctionPreference QuestionableResult =
129 getLangOpts().CUDADisableTargetCallChecks ? CFP_LastResort : CFP_Never;
130
131 // (d) HostDevice behavior depends on compilation mode.
132 if (CallerTarget == CFT_HostDevice) {
133 // Calling a function that matches compilation mode is OK.
134 // Calling a function from the other side is frowned upon.
135 if (getLangOpts().CUDAIsDevice)
136 return CalleeTarget == CFT_Device ? CFP_Fallback : QuestionableResult;
137 else
138 return (CalleeTarget == CFT_Host || CalleeTarget == CFT_Global)
139 ? CFP_Fallback
140 : QuestionableResult;
141 }
142
143 // (e) Calling across device/host boundary is not something you should do.
144 if ((CallerTarget == CFT_Host && CalleeTarget == CFT_Device) ||
145 (CallerTarget == CFT_Device && CalleeTarget == CFT_Host) ||
146 (CallerTarget == CFT_Global && CalleeTarget == CFT_Host))
147 return QuestionableResult;
148
149 llvm_unreachable("All cases should've been handled by now.");
150}
151
Eli Bendersky9a220fc2014-09-29 20:38:29 +0000152bool Sema::CheckCUDATarget(const FunctionDecl *Caller,
153 const FunctionDecl *Callee) {
Artem Belevich94a55e82015-09-22 17:22:59 +0000154 // With target overloads enabled, we only disallow calling
155 // combinations with CFP_Never.
156 if (getLangOpts().CUDATargetOverloads)
157 return IdentifyCUDAPreference(Caller,Callee) == CFP_Never;
158
Eli Bendersky4bdc50e2015-04-15 22:27:06 +0000159 // The CUDADisableTargetCallChecks short-circuits this check: we assume all
160 // cross-target calls are valid.
161 if (getLangOpts().CUDADisableTargetCallChecks)
162 return false;
163
Jacques Pienaar5bdd6772014-12-16 20:12:38 +0000164 CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller),
165 CalleeTarget = IdentifyCUDATarget(Callee);
Eli Bendersky9a220fc2014-09-29 20:38:29 +0000166
Eli Bendersky9a220fc2014-09-29 20:38:29 +0000167 // If one of the targets is invalid, the check always fails, no matter what
168 // the other target is.
169 if (CallerTarget == CFT_InvalidTarget || CalleeTarget == CFT_InvalidTarget)
170 return true;
171
Reid Klecknerbbc01782014-12-03 21:53:36 +0000172 // CUDA B.1.1 "The __device__ qualifier declares a function that is [...]
Eli Bendersky7325e562014-09-03 15:27:03 +0000173 // Callable from the device only."
174 if (CallerTarget == CFT_Host && CalleeTarget == CFT_Device)
175 return true;
176
Reid Klecknerbbc01782014-12-03 21:53:36 +0000177 // CUDA B.1.2 "The __global__ qualifier declares a function that is [...]
Eli Bendersky7325e562014-09-03 15:27:03 +0000178 // Callable from the host only."
Reid Klecknerbbc01782014-12-03 21:53:36 +0000179 // CUDA B.1.3 "The __host__ qualifier declares a function that is [...]
Eli Bendersky7325e562014-09-03 15:27:03 +0000180 // Callable from the host only."
181 if ((CallerTarget == CFT_Device || CallerTarget == CFT_Global) &&
182 (CalleeTarget == CFT_Host || CalleeTarget == CFT_Global))
183 return true;
184
Reid Klecknerbbc01782014-12-03 21:53:36 +0000185 // CUDA B.1.3 "The __device__ and __host__ qualifiers can be used together
186 // however, in which case the function is compiled for both the host and the
187 // device. The __CUDA_ARCH__ macro [...] can be used to differentiate code
188 // paths between host and device."
Reid Klecknerbbc01782014-12-03 21:53:36 +0000189 if (CallerTarget == CFT_HostDevice && CalleeTarget != CFT_HostDevice) {
Jacques Pienaar5bdd6772014-12-16 20:12:38 +0000190 // If the caller is implicit then the check always passes.
191 if (Caller->isImplicit()) return false;
192
193 bool InDeviceMode = getLangOpts().CUDAIsDevice;
Jacques Pienaara50178c2015-02-24 21:45:33 +0000194 if (!InDeviceMode && CalleeTarget != CFT_Host)
195 return true;
196 if (InDeviceMode && CalleeTarget != CFT_Device) {
197 // Allow host device functions to call host functions if explicitly
198 // requested.
199 if (CalleeTarget == CFT_Host &&
200 getLangOpts().CUDAAllowHostCallsFromHostDevice) {
201 Diag(Caller->getLocation(),
202 diag::warn_host_calls_from_host_device)
203 << Callee->getNameAsString() << Caller->getNameAsString();
204 return false;
205 }
206
Reid Klecknerbbc01782014-12-03 21:53:36 +0000207 return true;
Jacques Pienaara50178c2015-02-24 21:45:33 +0000208 }
Reid Klecknerbbc01782014-12-03 21:53:36 +0000209 }
Eli Bendersky7325e562014-09-03 15:27:03 +0000210
211 return false;
212}
213
Artem Belevich94a55e82015-09-22 17:22:59 +0000214template <typename T, typename FetchDeclFn>
215static void EraseUnwantedCUDAMatchesImpl(Sema &S, const FunctionDecl *Caller,
216 llvm::SmallVectorImpl<T> &Matches,
217 FetchDeclFn FetchDecl) {
218 assert(S.getLangOpts().CUDATargetOverloads &&
219 "Should not be called w/o enabled target overloads.");
220 if (Matches.size() <= 1)
221 return;
222
223 // Find the best call preference among the functions in Matches.
224 Sema::CUDAFunctionPreference P, BestCFP = Sema::CFP_Never;
225 for (auto const &Match : Matches) {
226 P = S.IdentifyCUDAPreference(Caller, FetchDecl(Match));
227 if (P > BestCFP)
228 BestCFP = P;
229 }
230
231 // Erase all functions with lower priority.
232 for (unsigned I = 0, N = Matches.size(); I != N;)
233 if (S.IdentifyCUDAPreference(Caller, FetchDecl(Matches[I])) < BestCFP) {
234 Matches[I] = Matches[--N];
235 Matches.resize(N);
236 } else {
237 ++I;
238 }
239}
240
241void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
242 SmallVectorImpl<FunctionDecl *> &Matches){
243 EraseUnwantedCUDAMatchesImpl<FunctionDecl *>(
244 *this, Caller, Matches, [](const FunctionDecl *item) { return item; });
245}
246
247void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
248 SmallVectorImpl<DeclAccessPair> &Matches) {
249 EraseUnwantedCUDAMatchesImpl<DeclAccessPair>(
250 *this, Caller, Matches, [](const DeclAccessPair &item) {
251 return dyn_cast<FunctionDecl>(item.getDecl());
252 });
253}
254
255void Sema::EraseUnwantedCUDAMatches(
256 const FunctionDecl *Caller,
257 SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches){
258 EraseUnwantedCUDAMatchesImpl<std::pair<DeclAccessPair, FunctionDecl *>>(
259 *this, Caller, Matches,
260 [](const std::pair<DeclAccessPair, FunctionDecl *> &item) {
261 return dyn_cast<FunctionDecl>(item.second);
262 });
263}
264
Eli Bendersky9a220fc2014-09-29 20:38:29 +0000265/// When an implicitly-declared special member has to invoke more than one
266/// base/field special member, conflicts may occur in the targets of these
267/// members. For example, if one base's member __host__ and another's is
268/// __device__, it's a conflict.
269/// This function figures out if the given targets \param Target1 and
270/// \param Target2 conflict, and if they do not it fills in
271/// \param ResolvedTarget with a target that resolves for both calls.
272/// \return true if there's a conflict, false otherwise.
273static bool
274resolveCalleeCUDATargetConflict(Sema::CUDAFunctionTarget Target1,
275 Sema::CUDAFunctionTarget Target2,
276 Sema::CUDAFunctionTarget *ResolvedTarget) {
Justin Lebarc66a1062016-01-20 00:26:57 +0000277 // Only free functions and static member functions may be global.
278 assert(Target1 != Sema::CFT_Global);
279 assert(Target2 != Sema::CFT_Global);
Eli Bendersky9a220fc2014-09-29 20:38:29 +0000280
281 if (Target1 == Sema::CFT_HostDevice) {
282 *ResolvedTarget = Target2;
283 } else if (Target2 == Sema::CFT_HostDevice) {
284 *ResolvedTarget = Target1;
285 } else if (Target1 != Target2) {
286 return true;
287 } else {
288 *ResolvedTarget = Target1;
289 }
290
291 return false;
292}
293
294bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl,
295 CXXSpecialMember CSM,
296 CXXMethodDecl *MemberDecl,
297 bool ConstRHS,
298 bool Diagnose) {
299 llvm::Optional<CUDAFunctionTarget> InferredTarget;
300
301 // We're going to invoke special member lookup; mark that these special
302 // members are called from this one, and not from its caller.
303 ContextRAII MethodContext(*this, MemberDecl);
304
305 // Look for special members in base classes that should be invoked from here.
306 // Infer the target of this member base on the ones it should call.
307 // Skip direct and indirect virtual bases for abstract classes.
308 llvm::SmallVector<const CXXBaseSpecifier *, 16> Bases;
309 for (const auto &B : ClassDecl->bases()) {
310 if (!B.isVirtual()) {
311 Bases.push_back(&B);
312 }
313 }
314
315 if (!ClassDecl->isAbstract()) {
316 for (const auto &VB : ClassDecl->vbases()) {
317 Bases.push_back(&VB);
318 }
319 }
320
321 for (const auto *B : Bases) {
322 const RecordType *BaseType = B->getType()->getAs<RecordType>();
323 if (!BaseType) {
324 continue;
325 }
326
327 CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
328 Sema::SpecialMemberOverloadResult *SMOR =
329 LookupSpecialMember(BaseClassDecl, CSM,
330 /* ConstArg */ ConstRHS,
331 /* VolatileArg */ false,
332 /* RValueThis */ false,
333 /* ConstThis */ false,
334 /* VolatileThis */ false);
335
336 if (!SMOR || !SMOR->getMethod()) {
337 continue;
338 }
339
340 CUDAFunctionTarget BaseMethodTarget = IdentifyCUDATarget(SMOR->getMethod());
341 if (!InferredTarget.hasValue()) {
342 InferredTarget = BaseMethodTarget;
343 } else {
344 bool ResolutionError = resolveCalleeCUDATargetConflict(
345 InferredTarget.getValue(), BaseMethodTarget,
346 InferredTarget.getPointer());
347 if (ResolutionError) {
348 if (Diagnose) {
349 Diag(ClassDecl->getLocation(),
350 diag::note_implicit_member_target_infer_collision)
351 << (unsigned)CSM << InferredTarget.getValue() << BaseMethodTarget;
352 }
353 MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context));
354 return true;
355 }
356 }
357 }
358
359 // Same as for bases, but now for special members of fields.
360 for (const auto *F : ClassDecl->fields()) {
361 if (F->isInvalidDecl()) {
362 continue;
363 }
364
365 const RecordType *FieldType =
366 Context.getBaseElementType(F->getType())->getAs<RecordType>();
367 if (!FieldType) {
368 continue;
369 }
370
371 CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(FieldType->getDecl());
372 Sema::SpecialMemberOverloadResult *SMOR =
373 LookupSpecialMember(FieldRecDecl, CSM,
374 /* ConstArg */ ConstRHS && !F->isMutable(),
375 /* VolatileArg */ false,
376 /* RValueThis */ false,
377 /* ConstThis */ false,
378 /* VolatileThis */ false);
379
380 if (!SMOR || !SMOR->getMethod()) {
381 continue;
382 }
383
384 CUDAFunctionTarget FieldMethodTarget =
385 IdentifyCUDATarget(SMOR->getMethod());
386 if (!InferredTarget.hasValue()) {
387 InferredTarget = FieldMethodTarget;
388 } else {
389 bool ResolutionError = resolveCalleeCUDATargetConflict(
390 InferredTarget.getValue(), FieldMethodTarget,
391 InferredTarget.getPointer());
392 if (ResolutionError) {
393 if (Diagnose) {
394 Diag(ClassDecl->getLocation(),
395 diag::note_implicit_member_target_infer_collision)
396 << (unsigned)CSM << InferredTarget.getValue()
397 << FieldMethodTarget;
398 }
399 MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context));
400 return true;
401 }
402 }
403 }
404
405 if (InferredTarget.hasValue()) {
406 if (InferredTarget.getValue() == CFT_Device) {
407 MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
408 } else if (InferredTarget.getValue() == CFT_Host) {
409 MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
410 } else {
411 MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
412 MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
413 }
414 } else {
415 // If no target was inferred, mark this member as __host__ __device__;
416 // it's the least restrictive option that can be invoked from any target.
417 MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
418 MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
419 }
420
421 return false;
422}
Artem Belevich97c01c32016-02-02 22:29:48 +0000423
424bool Sema::isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD) {
425 if (!CD->isDefined() && CD->isTemplateInstantiation())
426 InstantiateFunctionDefinition(Loc, CD->getFirstDecl());
427
428 // (E.2.3.1, CUDA 7.5) A constructor for a class type is considered
429 // empty at a point in the translation unit, if it is either a
430 // trivial constructor
431 if (CD->isTrivial())
432 return true;
433
434 // ... or it satisfies all of the following conditions:
435 // The constructor function has been defined.
436 // The constructor function has no parameters,
437 // and the function body is an empty compound statement.
438 if (!(CD->hasTrivialBody() && CD->getNumParams() == 0))
439 return false;
440
441 // Its class has no virtual functions and no virtual base classes.
442 if (CD->getParent()->isDynamicClass())
443 return false;
444
445 // The only form of initializer allowed is an empty constructor.
446 // This will recursively checks all base classes and member initializers
447 if (!llvm::all_of(CD->inits(), [&](const CXXCtorInitializer *CI) {
448 if (const CXXConstructExpr *CE =
449 dyn_cast<CXXConstructExpr>(CI->getInit()))
450 return isEmptyCudaConstructor(Loc, CE->getConstructor());
451 return false;
452 }))
453 return false;
454
455 return true;
456}