blob: 07a5ac328077db63196893e62b66c071c26b55c4 [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)
Justin Lebar39186472016-03-29 16:24:22 +000071// Preferences: N:native, SS:same side, HD:host-device, WS:wrong side, --:never.
Artem Belevich94a55e82015-09-22 17:22:59 +000072//
Artem Belevich18609102016-02-12 18:29:18 +000073// | F | T | Ph | Pd | H |
74// |----+----+-----+-----+-----+
75// | d | d | N | N | (c) |
76// | d | g | -- | -- | (a) |
77// | d | h | -- | -- | (e) |
78// | d | hd | HD | HD | (b) |
79// | g | d | N | N | (c) |
80// | g | g | -- | -- | (a) |
81// | g | h | -- | -- | (e) |
82// | g | hd | HD | HD | (b) |
83// | h | d | -- | -- | (e) |
84// | h | g | N | N | (c) |
85// | h | h | N | N | (c) |
86// | h | hd | HD | HD | (b) |
87// | hd | d | WS | SS | (d) |
88// | hd | g | SS | -- |(d/a)|
89// | hd | h | SS | WS | (d) |
90// | hd | hd | HD | HD | (b) |
Artem Belevich94a55e82015-09-22 17:22:59 +000091
92Sema::CUDAFunctionPreference
93Sema::IdentifyCUDAPreference(const FunctionDecl *Caller,
94 const FunctionDecl *Callee) {
Artem Belevich94a55e82015-09-22 17:22:59 +000095 assert(Callee && "Callee must be valid.");
96 CUDAFunctionTarget CalleeTarget = IdentifyCUDATarget(Callee);
97 CUDAFunctionTarget CallerTarget =
98 (Caller != nullptr) ? IdentifyCUDATarget(Caller) : Sema::CFT_Host;
99
100 // If one of the targets is invalid, the check always fails, no matter what
101 // the other target is.
102 if (CallerTarget == CFT_InvalidTarget || CalleeTarget == CFT_InvalidTarget)
103 return CFP_Never;
104
105 // (a) Can't call global from some contexts until we support CUDA's
106 // dynamic parallelism.
107 if (CalleeTarget == CFT_Global &&
108 (CallerTarget == CFT_Global || CallerTarget == CFT_Device ||
109 (CallerTarget == CFT_HostDevice && getLangOpts().CUDAIsDevice)))
110 return CFP_Never;
111
Artem Belevich18609102016-02-12 18:29:18 +0000112 // (b) Calling HostDevice is OK for everyone.
113 if (CalleeTarget == CFT_HostDevice)
114 return CFP_HostDevice;
115
116 // (c) Best case scenarios
Artem Belevich94a55e82015-09-22 17:22:59 +0000117 if (CalleeTarget == CallerTarget ||
118 (CallerTarget == CFT_Host && CalleeTarget == CFT_Global) ||
119 (CallerTarget == CFT_Global && CalleeTarget == CFT_Device))
Artem Belevich18609102016-02-12 18:29:18 +0000120 return CFP_Native;
Artem Belevich94a55e82015-09-22 17:22:59 +0000121
122 // (d) HostDevice behavior depends on compilation mode.
123 if (CallerTarget == CFT_HostDevice) {
Artem Belevich18609102016-02-12 18:29:18 +0000124 // It's OK to call a compilation-mode matching function from an HD one.
125 if ((getLangOpts().CUDAIsDevice && CalleeTarget == CFT_Device) ||
126 (!getLangOpts().CUDAIsDevice &&
127 (CalleeTarget == CFT_Host || CalleeTarget == CFT_Global)))
128 return CFP_SameSide;
129
Justin Lebar25c4a812016-03-29 16:24:16 +0000130 // Calls from HD to non-mode-matching functions (i.e., to host functions
131 // when compiling in device mode or to device functions when compiling in
132 // host mode) are allowed at the sema level, but eventually rejected if
133 // they're ever codegened. TODO: Reject said calls earlier.
134 return CFP_WrongSide;
Artem Belevich94a55e82015-09-22 17:22:59 +0000135 }
136
137 // (e) Calling across device/host boundary is not something you should do.
138 if ((CallerTarget == CFT_Host && CalleeTarget == CFT_Device) ||
139 (CallerTarget == CFT_Device && CalleeTarget == CFT_Host) ||
140 (CallerTarget == CFT_Global && CalleeTarget == CFT_Host))
Artem Belevich18609102016-02-12 18:29:18 +0000141 return CFP_Never;
Artem Belevich94a55e82015-09-22 17:22:59 +0000142
143 llvm_unreachable("All cases should've been handled by now.");
144}
145
Justin Lebare6a2cc12016-03-22 00:09:25 +0000146template <typename T>
147static void EraseUnwantedCUDAMatchesImpl(
148 Sema &S, const FunctionDecl *Caller, llvm::SmallVectorImpl<T> &Matches,
149 std::function<const FunctionDecl *(const T &)> FetchDecl) {
Artem Belevich94a55e82015-09-22 17:22:59 +0000150 if (Matches.size() <= 1)
151 return;
152
Justin Lebare6a2cc12016-03-22 00:09:25 +0000153 // Gets the CUDA function preference for a call from Caller to Match.
154 auto GetCFP = [&](const T &Match) {
155 return S.IdentifyCUDAPreference(Caller, FetchDecl(Match));
156 };
157
Artem Belevich94a55e82015-09-22 17:22:59 +0000158 // Find the best call preference among the functions in Matches.
Justin Lebare6a2cc12016-03-22 00:09:25 +0000159 Sema::CUDAFunctionPreference BestCFP = GetCFP(*std::max_element(
160 Matches.begin(), Matches.end(),
161 [&](const T &M1, const T &M2) { return GetCFP(M1) < GetCFP(M2); }));
Artem Belevich94a55e82015-09-22 17:22:59 +0000162
163 // Erase all functions with lower priority.
Justin Lebare6a2cc12016-03-22 00:09:25 +0000164 Matches.erase(llvm::remove_if(
165 Matches, [&](const T &Match) { return GetCFP(Match) < BestCFP; }));
Artem Belevich94a55e82015-09-22 17:22:59 +0000166}
167
168void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
169 SmallVectorImpl<FunctionDecl *> &Matches){
170 EraseUnwantedCUDAMatchesImpl<FunctionDecl *>(
171 *this, Caller, Matches, [](const FunctionDecl *item) { return item; });
172}
173
174void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
175 SmallVectorImpl<DeclAccessPair> &Matches) {
176 EraseUnwantedCUDAMatchesImpl<DeclAccessPair>(
177 *this, Caller, Matches, [](const DeclAccessPair &item) {
178 return dyn_cast<FunctionDecl>(item.getDecl());
179 });
180}
181
182void Sema::EraseUnwantedCUDAMatches(
183 const FunctionDecl *Caller,
184 SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches){
185 EraseUnwantedCUDAMatchesImpl<std::pair<DeclAccessPair, FunctionDecl *>>(
186 *this, Caller, Matches,
187 [](const std::pair<DeclAccessPair, FunctionDecl *> &item) {
188 return dyn_cast<FunctionDecl>(item.second);
189 });
190}
191
Eli Bendersky9a220fc2014-09-29 20:38:29 +0000192/// When an implicitly-declared special member has to invoke more than one
193/// base/field special member, conflicts may occur in the targets of these
194/// members. For example, if one base's member __host__ and another's is
195/// __device__, it's a conflict.
196/// This function figures out if the given targets \param Target1 and
197/// \param Target2 conflict, and if they do not it fills in
198/// \param ResolvedTarget with a target that resolves for both calls.
199/// \return true if there's a conflict, false otherwise.
200static bool
201resolveCalleeCUDATargetConflict(Sema::CUDAFunctionTarget Target1,
202 Sema::CUDAFunctionTarget Target2,
203 Sema::CUDAFunctionTarget *ResolvedTarget) {
Justin Lebarc66a1062016-01-20 00:26:57 +0000204 // Only free functions and static member functions may be global.
205 assert(Target1 != Sema::CFT_Global);
206 assert(Target2 != Sema::CFT_Global);
Eli Bendersky9a220fc2014-09-29 20:38:29 +0000207
208 if (Target1 == Sema::CFT_HostDevice) {
209 *ResolvedTarget = Target2;
210 } else if (Target2 == Sema::CFT_HostDevice) {
211 *ResolvedTarget = Target1;
212 } else if (Target1 != Target2) {
213 return true;
214 } else {
215 *ResolvedTarget = Target1;
216 }
217
218 return false;
219}
220
221bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl,
222 CXXSpecialMember CSM,
223 CXXMethodDecl *MemberDecl,
224 bool ConstRHS,
225 bool Diagnose) {
226 llvm::Optional<CUDAFunctionTarget> InferredTarget;
227
228 // We're going to invoke special member lookup; mark that these special
229 // members are called from this one, and not from its caller.
230 ContextRAII MethodContext(*this, MemberDecl);
231
232 // Look for special members in base classes that should be invoked from here.
233 // Infer the target of this member base on the ones it should call.
234 // Skip direct and indirect virtual bases for abstract classes.
235 llvm::SmallVector<const CXXBaseSpecifier *, 16> Bases;
236 for (const auto &B : ClassDecl->bases()) {
237 if (!B.isVirtual()) {
238 Bases.push_back(&B);
239 }
240 }
241
242 if (!ClassDecl->isAbstract()) {
243 for (const auto &VB : ClassDecl->vbases()) {
244 Bases.push_back(&VB);
245 }
246 }
247
248 for (const auto *B : Bases) {
249 const RecordType *BaseType = B->getType()->getAs<RecordType>();
250 if (!BaseType) {
251 continue;
252 }
253
254 CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
255 Sema::SpecialMemberOverloadResult *SMOR =
256 LookupSpecialMember(BaseClassDecl, CSM,
257 /* ConstArg */ ConstRHS,
258 /* VolatileArg */ false,
259 /* RValueThis */ false,
260 /* ConstThis */ false,
261 /* VolatileThis */ false);
262
263 if (!SMOR || !SMOR->getMethod()) {
264 continue;
265 }
266
267 CUDAFunctionTarget BaseMethodTarget = IdentifyCUDATarget(SMOR->getMethod());
268 if (!InferredTarget.hasValue()) {
269 InferredTarget = BaseMethodTarget;
270 } else {
271 bool ResolutionError = resolveCalleeCUDATargetConflict(
272 InferredTarget.getValue(), BaseMethodTarget,
273 InferredTarget.getPointer());
274 if (ResolutionError) {
275 if (Diagnose) {
276 Diag(ClassDecl->getLocation(),
277 diag::note_implicit_member_target_infer_collision)
278 << (unsigned)CSM << InferredTarget.getValue() << BaseMethodTarget;
279 }
280 MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context));
281 return true;
282 }
283 }
284 }
285
286 // Same as for bases, but now for special members of fields.
287 for (const auto *F : ClassDecl->fields()) {
288 if (F->isInvalidDecl()) {
289 continue;
290 }
291
292 const RecordType *FieldType =
293 Context.getBaseElementType(F->getType())->getAs<RecordType>();
294 if (!FieldType) {
295 continue;
296 }
297
298 CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(FieldType->getDecl());
299 Sema::SpecialMemberOverloadResult *SMOR =
300 LookupSpecialMember(FieldRecDecl, CSM,
301 /* ConstArg */ ConstRHS && !F->isMutable(),
302 /* VolatileArg */ false,
303 /* RValueThis */ false,
304 /* ConstThis */ false,
305 /* VolatileThis */ false);
306
307 if (!SMOR || !SMOR->getMethod()) {
308 continue;
309 }
310
311 CUDAFunctionTarget FieldMethodTarget =
312 IdentifyCUDATarget(SMOR->getMethod());
313 if (!InferredTarget.hasValue()) {
314 InferredTarget = FieldMethodTarget;
315 } else {
316 bool ResolutionError = resolveCalleeCUDATargetConflict(
317 InferredTarget.getValue(), FieldMethodTarget,
318 InferredTarget.getPointer());
319 if (ResolutionError) {
320 if (Diagnose) {
321 Diag(ClassDecl->getLocation(),
322 diag::note_implicit_member_target_infer_collision)
323 << (unsigned)CSM << InferredTarget.getValue()
324 << FieldMethodTarget;
325 }
326 MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context));
327 return true;
328 }
329 }
330 }
331
332 if (InferredTarget.hasValue()) {
333 if (InferredTarget.getValue() == CFT_Device) {
334 MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
335 } else if (InferredTarget.getValue() == CFT_Host) {
336 MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
337 } else {
338 MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
339 MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
340 }
341 } else {
342 // If no target was inferred, mark this member as __host__ __device__;
343 // it's the least restrictive option that can be invoked from any target.
344 MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
345 MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
346 }
347
348 return false;
349}
Artem Belevich97c01c32016-02-02 22:29:48 +0000350
351bool Sema::isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD) {
352 if (!CD->isDefined() && CD->isTemplateInstantiation())
353 InstantiateFunctionDefinition(Loc, CD->getFirstDecl());
354
355 // (E.2.3.1, CUDA 7.5) A constructor for a class type is considered
356 // empty at a point in the translation unit, if it is either a
357 // trivial constructor
358 if (CD->isTrivial())
359 return true;
360
361 // ... or it satisfies all of the following conditions:
362 // The constructor function has been defined.
363 // The constructor function has no parameters,
364 // and the function body is an empty compound statement.
365 if (!(CD->hasTrivialBody() && CD->getNumParams() == 0))
366 return false;
367
368 // Its class has no virtual functions and no virtual base classes.
369 if (CD->getParent()->isDynamicClass())
370 return false;
371
372 // The only form of initializer allowed is an empty constructor.
373 // This will recursively checks all base classes and member initializers
374 if (!llvm::all_of(CD->inits(), [&](const CXXCtorInitializer *CI) {
375 if (const CXXConstructExpr *CE =
376 dyn_cast<CXXConstructExpr>(CI->getInit()))
377 return isEmptyCudaConstructor(Loc, CE->getConstructor());
378 return false;
379 }))
380 return false;
381
382 return true;
383}