1 //===--- 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"
17 #include "clang/AST/ExprCXX.h"
18 #include "clang/Lex/Preprocessor.h"
19 #include "clang/Sema/SemaDiagnostic.h"
20 #include "llvm/ADT/Optional.h"
21 #include "llvm/ADT/SmallVector.h"
22 using namespace clang;
23 
24 ExprResult 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
42 Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {
43   if (D->hasAttr<CUDAInvalidTargetAttr>())
44     return CFT_InvalidTarget;
45 
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;
53   } 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;
59   }
60 
61   return CFT_Host;
62 }
63 
64 // * 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: N:native, HD:host-device, SS:same side, WS:wrong side, --:never.
72 //
73 // | 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) |
91 
92 Sema::CUDAFunctionPreference
93 Sema::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) Calling HostDevice is OK for everyone.
116   if (CalleeTarget == CFT_HostDevice)
117     return CFP_HostDevice;
118 
119   // (c) Best case scenarios
120   if (CalleeTarget == CallerTarget ||
121       (CallerTarget == CFT_Host && CalleeTarget == CFT_Global) ||
122       (CallerTarget == CFT_Global && CalleeTarget == CFT_Device))
123     return CFP_Native;
124 
125   // (d) HostDevice behavior depends on compilation mode.
126   if (CallerTarget == CFT_HostDevice) {
127     // It's OK to call a compilation-mode matching function from an HD one.
128     if ((getLangOpts().CUDAIsDevice && CalleeTarget == CFT_Device) ||
129         (!getLangOpts().CUDAIsDevice &&
130          (CalleeTarget == CFT_Host || CalleeTarget == CFT_Global)))
131       return CFP_SameSide;
132 
133     // We'll allow calls to non-mode-matching functions if target call
134     // checks are disabled. This is needed to avoid complaining about
135     // HD->H calls when we compile for device side and vice versa.
136     if (getLangOpts().CUDADisableTargetCallChecks)
137       return CFP_WrongSide;
138 
139     return CFP_Never;
140   }
141 
142   // (e) Calling across device/host boundary is not something you should do.
143   if ((CallerTarget == CFT_Host && CalleeTarget == CFT_Device) ||
144       (CallerTarget == CFT_Device && CalleeTarget == CFT_Host) ||
145       (CallerTarget == CFT_Global && CalleeTarget == CFT_Host))
146     return CFP_Never;
147 
148   llvm_unreachable("All cases should've been handled by now.");
149 }
150 
151 bool Sema::CheckCUDATarget(const FunctionDecl *Caller,
152                            const FunctionDecl *Callee) {
153   // With target overloads enabled, we only disallow calling
154   // combinations with CFP_Never.
155   if (getLangOpts().CUDATargetOverloads)
156     return IdentifyCUDAPreference(Caller,Callee) == CFP_Never;
157 
158   // The CUDADisableTargetCallChecks short-circuits this check: we assume all
159   // cross-target calls are valid.
160   if (getLangOpts().CUDADisableTargetCallChecks)
161     return false;
162 
163   CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller),
164                      CalleeTarget = IdentifyCUDATarget(Callee);
165 
166   // If one of the targets is invalid, the check always fails, no matter what
167   // the other target is.
168   if (CallerTarget == CFT_InvalidTarget || CalleeTarget == CFT_InvalidTarget)
169     return true;
170 
171   // CUDA B.1.1 "The __device__ qualifier declares a function that is [...]
172   // Callable from the device only."
173   if (CallerTarget == CFT_Host && CalleeTarget == CFT_Device)
174     return true;
175 
176   // CUDA B.1.2 "The __global__ qualifier declares a function that is [...]
177   // Callable from the host only."
178   // CUDA B.1.3 "The __host__ qualifier declares a function that is [...]
179   // Callable from the host only."
180   if ((CallerTarget == CFT_Device || CallerTarget == CFT_Global) &&
181       (CalleeTarget == CFT_Host || CalleeTarget == CFT_Global))
182     return true;
183 
184   // CUDA B.1.3 "The __device__ and __host__ qualifiers can be used together
185   // however, in which case the function is compiled for both the host and the
186   // device. The __CUDA_ARCH__ macro [...] can be used to differentiate code
187   // paths between host and device."
188   if (CallerTarget == CFT_HostDevice && CalleeTarget != CFT_HostDevice) {
189     // If the caller is implicit then the check always passes.
190     if (Caller->isImplicit()) return false;
191 
192     bool InDeviceMode = getLangOpts().CUDAIsDevice;
193     if (!InDeviceMode && CalleeTarget != CFT_Host)
194         return true;
195     if (InDeviceMode && CalleeTarget != CFT_Device) {
196       // Allow host device functions to call host functions if explicitly
197       // requested.
198       if (CalleeTarget == CFT_Host &&
199           getLangOpts().CUDAAllowHostCallsFromHostDevice) {
200         Diag(Caller->getLocation(),
201              diag::warn_host_calls_from_host_device)
202             << Callee->getNameAsString() << Caller->getNameAsString();
203         return false;
204       }
205 
206       return true;
207     }
208   }
209 
210   return false;
211 }
212 
213 template <typename T>
214 static void EraseUnwantedCUDAMatchesImpl(
215     Sema &S, const FunctionDecl *Caller, llvm::SmallVectorImpl<T> &Matches,
216     std::function<const FunctionDecl *(const T &)> FetchDecl) {
217   assert(S.getLangOpts().CUDATargetOverloads &&
218          "Should not be called w/o enabled target overloads.");
219   if (Matches.size() <= 1)
220     return;
221 
222   // Gets the CUDA function preference for a call from Caller to Match.
223   auto GetCFP = [&](const T &Match) {
224     return S.IdentifyCUDAPreference(Caller, FetchDecl(Match));
225   };
226 
227   // Find the best call preference among the functions in Matches.
228   Sema::CUDAFunctionPreference BestCFP = GetCFP(*std::max_element(
229       Matches.begin(), Matches.end(),
230       [&](const T &M1, const T &M2) { return GetCFP(M1) < GetCFP(M2); }));
231 
232   // Erase all functions with lower priority.
233   Matches.erase(llvm::remove_if(
234       Matches, [&](const T &Match) { return GetCFP(Match) < BestCFP; }));
235 }
236 
237 void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
238                                     SmallVectorImpl<FunctionDecl *> &Matches){
239   EraseUnwantedCUDAMatchesImpl<FunctionDecl *>(
240       *this, Caller, Matches, [](const FunctionDecl *item) { return item; });
241 }
242 
243 void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
244                                     SmallVectorImpl<DeclAccessPair> &Matches) {
245   EraseUnwantedCUDAMatchesImpl<DeclAccessPair>(
246       *this, Caller, Matches, [](const DeclAccessPair &item) {
247         return dyn_cast<FunctionDecl>(item.getDecl());
248       });
249 }
250 
251 void Sema::EraseUnwantedCUDAMatches(
252     const FunctionDecl *Caller,
253     SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches){
254   EraseUnwantedCUDAMatchesImpl<std::pair<DeclAccessPair, FunctionDecl *>>(
255       *this, Caller, Matches,
256       [](const std::pair<DeclAccessPair, FunctionDecl *> &item) {
257         return dyn_cast<FunctionDecl>(item.second);
258       });
259 }
260 
261 /// When an implicitly-declared special member has to invoke more than one
262 /// base/field special member, conflicts may occur in the targets of these
263 /// members. For example, if one base's member __host__ and another's is
264 /// __device__, it's a conflict.
265 /// This function figures out if the given targets \param Target1 and
266 /// \param Target2 conflict, and if they do not it fills in
267 /// \param ResolvedTarget with a target that resolves for both calls.
268 /// \return true if there's a conflict, false otherwise.
269 static bool
270 resolveCalleeCUDATargetConflict(Sema::CUDAFunctionTarget Target1,
271                                 Sema::CUDAFunctionTarget Target2,
272                                 Sema::CUDAFunctionTarget *ResolvedTarget) {
273   // Only free functions and static member functions may be global.
274   assert(Target1 != Sema::CFT_Global);
275   assert(Target2 != Sema::CFT_Global);
276 
277   if (Target1 == Sema::CFT_HostDevice) {
278     *ResolvedTarget = Target2;
279   } else if (Target2 == Sema::CFT_HostDevice) {
280     *ResolvedTarget = Target1;
281   } else if (Target1 != Target2) {
282     return true;
283   } else {
284     *ResolvedTarget = Target1;
285   }
286 
287   return false;
288 }
289 
290 bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl,
291                                                    CXXSpecialMember CSM,
292                                                    CXXMethodDecl *MemberDecl,
293                                                    bool ConstRHS,
294                                                    bool Diagnose) {
295   llvm::Optional<CUDAFunctionTarget> InferredTarget;
296 
297   // We're going to invoke special member lookup; mark that these special
298   // members are called from this one, and not from its caller.
299   ContextRAII MethodContext(*this, MemberDecl);
300 
301   // Look for special members in base classes that should be invoked from here.
302   // Infer the target of this member base on the ones it should call.
303   // Skip direct and indirect virtual bases for abstract classes.
304   llvm::SmallVector<const CXXBaseSpecifier *, 16> Bases;
305   for (const auto &B : ClassDecl->bases()) {
306     if (!B.isVirtual()) {
307       Bases.push_back(&B);
308     }
309   }
310 
311   if (!ClassDecl->isAbstract()) {
312     for (const auto &VB : ClassDecl->vbases()) {
313       Bases.push_back(&VB);
314     }
315   }
316 
317   for (const auto *B : Bases) {
318     const RecordType *BaseType = B->getType()->getAs<RecordType>();
319     if (!BaseType) {
320       continue;
321     }
322 
323     CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
324     Sema::SpecialMemberOverloadResult *SMOR =
325         LookupSpecialMember(BaseClassDecl, CSM,
326                             /* ConstArg */ ConstRHS,
327                             /* VolatileArg */ false,
328                             /* RValueThis */ false,
329                             /* ConstThis */ false,
330                             /* VolatileThis */ false);
331 
332     if (!SMOR || !SMOR->getMethod()) {
333       continue;
334     }
335 
336     CUDAFunctionTarget BaseMethodTarget = IdentifyCUDATarget(SMOR->getMethod());
337     if (!InferredTarget.hasValue()) {
338       InferredTarget = BaseMethodTarget;
339     } else {
340       bool ResolutionError = resolveCalleeCUDATargetConflict(
341           InferredTarget.getValue(), BaseMethodTarget,
342           InferredTarget.getPointer());
343       if (ResolutionError) {
344         if (Diagnose) {
345           Diag(ClassDecl->getLocation(),
346                diag::note_implicit_member_target_infer_collision)
347               << (unsigned)CSM << InferredTarget.getValue() << BaseMethodTarget;
348         }
349         MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context));
350         return true;
351       }
352     }
353   }
354 
355   // Same as for bases, but now for special members of fields.
356   for (const auto *F : ClassDecl->fields()) {
357     if (F->isInvalidDecl()) {
358       continue;
359     }
360 
361     const RecordType *FieldType =
362         Context.getBaseElementType(F->getType())->getAs<RecordType>();
363     if (!FieldType) {
364       continue;
365     }
366 
367     CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(FieldType->getDecl());
368     Sema::SpecialMemberOverloadResult *SMOR =
369         LookupSpecialMember(FieldRecDecl, CSM,
370                             /* ConstArg */ ConstRHS && !F->isMutable(),
371                             /* VolatileArg */ false,
372                             /* RValueThis */ false,
373                             /* ConstThis */ false,
374                             /* VolatileThis */ false);
375 
376     if (!SMOR || !SMOR->getMethod()) {
377       continue;
378     }
379 
380     CUDAFunctionTarget FieldMethodTarget =
381         IdentifyCUDATarget(SMOR->getMethod());
382     if (!InferredTarget.hasValue()) {
383       InferredTarget = FieldMethodTarget;
384     } else {
385       bool ResolutionError = resolveCalleeCUDATargetConflict(
386           InferredTarget.getValue(), FieldMethodTarget,
387           InferredTarget.getPointer());
388       if (ResolutionError) {
389         if (Diagnose) {
390           Diag(ClassDecl->getLocation(),
391                diag::note_implicit_member_target_infer_collision)
392               << (unsigned)CSM << InferredTarget.getValue()
393               << FieldMethodTarget;
394         }
395         MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context));
396         return true;
397       }
398     }
399   }
400 
401   if (InferredTarget.hasValue()) {
402     if (InferredTarget.getValue() == CFT_Device) {
403       MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
404     } else if (InferredTarget.getValue() == CFT_Host) {
405       MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
406     } else {
407       MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
408       MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
409     }
410   } else {
411     // If no target was inferred, mark this member as __host__ __device__;
412     // it's the least restrictive option that can be invoked from any target.
413     MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
414     MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
415   }
416 
417   return false;
418 }
419 
420 bool Sema::isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD) {
421   if (!CD->isDefined() && CD->isTemplateInstantiation())
422     InstantiateFunctionDefinition(Loc, CD->getFirstDecl());
423 
424   // (E.2.3.1, CUDA 7.5) A constructor for a class type is considered
425   // empty at a point in the translation unit, if it is either a
426   // trivial constructor
427   if (CD->isTrivial())
428     return true;
429 
430   // ... or it satisfies all of the following conditions:
431   // The constructor function has been defined.
432   // The constructor function has no parameters,
433   // and the function body is an empty compound statement.
434   if (!(CD->hasTrivialBody() && CD->getNumParams() == 0))
435     return false;
436 
437   // Its class has no virtual functions and no virtual base classes.
438   if (CD->getParent()->isDynamicClass())
439     return false;
440 
441   // The only form of initializer allowed is an empty constructor.
442   // This will recursively checks all base classes and member initializers
443   if (!llvm::all_of(CD->inits(), [&](const CXXCtorInitializer *CI) {
444         if (const CXXConstructExpr *CE =
445                 dyn_cast<CXXConstructExpr>(CI->getInit()))
446           return isEmptyCudaConstructor(Loc, CE->getConstructor());
447         return false;
448       }))
449     return false;
450 
451   return true;
452 }
453