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, typename FetchDeclFn>
214 static void EraseUnwantedCUDAMatchesImpl(Sema &S, const FunctionDecl *Caller,
215                                          llvm::SmallVectorImpl<T> &Matches,
216                                          FetchDeclFn 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   // Find the best call preference among the functions in Matches.
223   Sema::CUDAFunctionPreference P, BestCFP = Sema::CFP_Never;
224   for (auto const &Match : Matches) {
225     P = S.IdentifyCUDAPreference(Caller, FetchDecl(Match));
226     if (P > BestCFP)
227       BestCFP = P;
228   }
229 
230   // Erase all functions with lower priority.
231   for (unsigned I = 0, N = Matches.size(); I != N;)
232     if (S.IdentifyCUDAPreference(Caller, FetchDecl(Matches[I])) < BestCFP) {
233       Matches[I] = Matches[--N];
234       Matches.resize(N);
235     } else {
236       ++I;
237     }
238 }
239 
240 void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
241                                     SmallVectorImpl<FunctionDecl *> &Matches){
242   EraseUnwantedCUDAMatchesImpl<FunctionDecl *>(
243       *this, Caller, Matches, [](const FunctionDecl *item) { return item; });
244 }
245 
246 void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
247                                     SmallVectorImpl<DeclAccessPair> &Matches) {
248   EraseUnwantedCUDAMatchesImpl<DeclAccessPair>(
249       *this, Caller, Matches, [](const DeclAccessPair &item) {
250         return dyn_cast<FunctionDecl>(item.getDecl());
251       });
252 }
253 
254 void Sema::EraseUnwantedCUDAMatches(
255     const FunctionDecl *Caller,
256     SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches){
257   EraseUnwantedCUDAMatchesImpl<std::pair<DeclAccessPair, FunctionDecl *>>(
258       *this, Caller, Matches,
259       [](const std::pair<DeclAccessPair, FunctionDecl *> &item) {
260         return dyn_cast<FunctionDecl>(item.second);
261       });
262 }
263 
264 /// When an implicitly-declared special member has to invoke more than one
265 /// base/field special member, conflicts may occur in the targets of these
266 /// members. For example, if one base's member __host__ and another's is
267 /// __device__, it's a conflict.
268 /// This function figures out if the given targets \param Target1 and
269 /// \param Target2 conflict, and if they do not it fills in
270 /// \param ResolvedTarget with a target that resolves for both calls.
271 /// \return true if there's a conflict, false otherwise.
272 static bool
273 resolveCalleeCUDATargetConflict(Sema::CUDAFunctionTarget Target1,
274                                 Sema::CUDAFunctionTarget Target2,
275                                 Sema::CUDAFunctionTarget *ResolvedTarget) {
276   // Only free functions and static member functions may be global.
277   assert(Target1 != Sema::CFT_Global);
278   assert(Target2 != Sema::CFT_Global);
279 
280   if (Target1 == Sema::CFT_HostDevice) {
281     *ResolvedTarget = Target2;
282   } else if (Target2 == Sema::CFT_HostDevice) {
283     *ResolvedTarget = Target1;
284   } else if (Target1 != Target2) {
285     return true;
286   } else {
287     *ResolvedTarget = Target1;
288   }
289 
290   return false;
291 }
292 
293 bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl,
294                                                    CXXSpecialMember CSM,
295                                                    CXXMethodDecl *MemberDecl,
296                                                    bool ConstRHS,
297                                                    bool Diagnose) {
298   llvm::Optional<CUDAFunctionTarget> InferredTarget;
299 
300   // We're going to invoke special member lookup; mark that these special
301   // members are called from this one, and not from its caller.
302   ContextRAII MethodContext(*this, MemberDecl);
303 
304   // Look for special members in base classes that should be invoked from here.
305   // Infer the target of this member base on the ones it should call.
306   // Skip direct and indirect virtual bases for abstract classes.
307   llvm::SmallVector<const CXXBaseSpecifier *, 16> Bases;
308   for (const auto &B : ClassDecl->bases()) {
309     if (!B.isVirtual()) {
310       Bases.push_back(&B);
311     }
312   }
313 
314   if (!ClassDecl->isAbstract()) {
315     for (const auto &VB : ClassDecl->vbases()) {
316       Bases.push_back(&VB);
317     }
318   }
319 
320   for (const auto *B : Bases) {
321     const RecordType *BaseType = B->getType()->getAs<RecordType>();
322     if (!BaseType) {
323       continue;
324     }
325 
326     CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
327     Sema::SpecialMemberOverloadResult *SMOR =
328         LookupSpecialMember(BaseClassDecl, CSM,
329                             /* ConstArg */ ConstRHS,
330                             /* VolatileArg */ false,
331                             /* RValueThis */ false,
332                             /* ConstThis */ false,
333                             /* VolatileThis */ false);
334 
335     if (!SMOR || !SMOR->getMethod()) {
336       continue;
337     }
338 
339     CUDAFunctionTarget BaseMethodTarget = IdentifyCUDATarget(SMOR->getMethod());
340     if (!InferredTarget.hasValue()) {
341       InferredTarget = BaseMethodTarget;
342     } else {
343       bool ResolutionError = resolveCalleeCUDATargetConflict(
344           InferredTarget.getValue(), BaseMethodTarget,
345           InferredTarget.getPointer());
346       if (ResolutionError) {
347         if (Diagnose) {
348           Diag(ClassDecl->getLocation(),
349                diag::note_implicit_member_target_infer_collision)
350               << (unsigned)CSM << InferredTarget.getValue() << BaseMethodTarget;
351         }
352         MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context));
353         return true;
354       }
355     }
356   }
357 
358   // Same as for bases, but now for special members of fields.
359   for (const auto *F : ClassDecl->fields()) {
360     if (F->isInvalidDecl()) {
361       continue;
362     }
363 
364     const RecordType *FieldType =
365         Context.getBaseElementType(F->getType())->getAs<RecordType>();
366     if (!FieldType) {
367       continue;
368     }
369 
370     CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(FieldType->getDecl());
371     Sema::SpecialMemberOverloadResult *SMOR =
372         LookupSpecialMember(FieldRecDecl, CSM,
373                             /* ConstArg */ ConstRHS && !F->isMutable(),
374                             /* VolatileArg */ false,
375                             /* RValueThis */ false,
376                             /* ConstThis */ false,
377                             /* VolatileThis */ false);
378 
379     if (!SMOR || !SMOR->getMethod()) {
380       continue;
381     }
382 
383     CUDAFunctionTarget FieldMethodTarget =
384         IdentifyCUDATarget(SMOR->getMethod());
385     if (!InferredTarget.hasValue()) {
386       InferredTarget = FieldMethodTarget;
387     } else {
388       bool ResolutionError = resolveCalleeCUDATargetConflict(
389           InferredTarget.getValue(), FieldMethodTarget,
390           InferredTarget.getPointer());
391       if (ResolutionError) {
392         if (Diagnose) {
393           Diag(ClassDecl->getLocation(),
394                diag::note_implicit_member_target_infer_collision)
395               << (unsigned)CSM << InferredTarget.getValue()
396               << FieldMethodTarget;
397         }
398         MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context));
399         return true;
400       }
401     }
402   }
403 
404   if (InferredTarget.hasValue()) {
405     if (InferredTarget.getValue() == CFT_Device) {
406       MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
407     } else if (InferredTarget.getValue() == CFT_Host) {
408       MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
409     } else {
410       MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
411       MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
412     }
413   } else {
414     // If no target was inferred, mark this member as __host__ __device__;
415     // it's the least restrictive option that can be invoked from any target.
416     MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
417     MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
418   }
419 
420   return false;
421 }
422 
423 bool Sema::isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD) {
424   if (!CD->isDefined() && CD->isTemplateInstantiation())
425     InstantiateFunctionDefinition(Loc, CD->getFirstDecl());
426 
427   // (E.2.3.1, CUDA 7.5) A constructor for a class type is considered
428   // empty at a point in the translation unit, if it is either a
429   // trivial constructor
430   if (CD->isTrivial())
431     return true;
432 
433   // ... or it satisfies all of the following conditions:
434   // The constructor function has been defined.
435   // The constructor function has no parameters,
436   // and the function body is an empty compound statement.
437   if (!(CD->hasTrivialBody() && CD->getNumParams() == 0))
438     return false;
439 
440   // Its class has no virtual functions and no virtual base classes.
441   if (CD->getParent()->isDynamicClass())
442     return false;
443 
444   // The only form of initializer allowed is an empty constructor.
445   // This will recursively checks all base classes and member initializers
446   if (!llvm::all_of(CD->inits(), [&](const CXXCtorInitializer *CI) {
447         if (const CXXConstructExpr *CE =
448                 dyn_cast<CXXConstructExpr>(CI->getInit()))
449           return isEmptyCudaConstructor(Loc, CE->getConstructor());
450         return false;
451       }))
452     return false;
453 
454   return true;
455 }
456