|
|
|||
File indexing completed on 2026-05-10 08:37:04
0001 //===----- SemaCUDA.h ----- Semantic Analysis for CUDA constructs ---------===// 0002 // 0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 0004 // See https://llvm.org/LICENSE.txt for license information. 0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 0006 // 0007 //===----------------------------------------------------------------------===// 0008 /// \file 0009 /// This file declares semantic analysis for CUDA constructs. 0010 /// 0011 //===----------------------------------------------------------------------===// 0012 0013 #ifndef LLVM_CLANG_SEMA_SEMACUDA_H 0014 #define LLVM_CLANG_SEMA_SEMACUDA_H 0015 0016 #include "clang/AST/ASTFwd.h" 0017 #include "clang/AST/DeclAccessPair.h" 0018 #include "clang/AST/Redeclarable.h" 0019 #include "clang/Basic/Cuda.h" 0020 #include "clang/Basic/LLVM.h" 0021 #include "clang/Basic/SourceLocation.h" 0022 #include "clang/Sema/Lookup.h" 0023 #include "clang/Sema/Ownership.h" 0024 #include "clang/Sema/SemaBase.h" 0025 #include "llvm/ADT/DenseMap.h" 0026 #include "llvm/ADT/DenseMapInfo.h" 0027 #include "llvm/ADT/DenseSet.h" 0028 #include "llvm/ADT/Hashing.h" 0029 #include "llvm/ADT/SmallVector.h" 0030 #include <string> 0031 #include <utility> 0032 0033 namespace clang { 0034 namespace sema { 0035 class Capture; 0036 } // namespace sema 0037 0038 class ASTReader; 0039 class ASTWriter; 0040 enum class CUDAFunctionTarget; 0041 enum class CXXSpecialMemberKind; 0042 class ParsedAttributesView; 0043 class Scope; 0044 0045 class SemaCUDA : public SemaBase { 0046 public: 0047 SemaCUDA(Sema &S); 0048 0049 /// Increments our count of the number of times we've seen a pragma forcing 0050 /// functions to be __host__ __device__. So long as this count is greater 0051 /// than zero, all functions encountered will be __host__ __device__. 0052 void PushForceHostDevice(); 0053 0054 /// Decrements our count of the number of times we've seen a pragma forcing 0055 /// functions to be __host__ __device__. Returns false if the count is 0 0056 /// before incrementing, so you can emit an error. 0057 bool PopForceHostDevice(); 0058 0059 ExprResult ActOnExecConfigExpr(Scope *S, SourceLocation LLLLoc, 0060 MultiExprArg ExecConfig, 0061 SourceLocation GGGLoc); 0062 0063 /// A pair of a canonical FunctionDecl and a SourceLocation. When used as the 0064 /// key in a hashtable, both the FD and location are hashed. 0065 struct FunctionDeclAndLoc { 0066 CanonicalDeclPtr<const FunctionDecl> FD; 0067 SourceLocation Loc; 0068 }; 0069 0070 /// FunctionDecls and SourceLocations for which CheckCall has emitted a 0071 /// (maybe deferred) "bad call" diagnostic. We use this to avoid emitting the 0072 /// same deferred diag twice. 0073 llvm::DenseSet<FunctionDeclAndLoc> LocsWithCUDACallDiags; 0074 0075 /// An inverse call graph, mapping known-emitted functions to one of their 0076 /// known-emitted callers (plus the location of the call). 0077 /// 0078 /// Functions that we can tell a priori must be emitted aren't added to this 0079 /// map. 0080 llvm::DenseMap</* Callee = */ CanonicalDeclPtr<const FunctionDecl>, 0081 /* Caller = */ FunctionDeclAndLoc> 0082 DeviceKnownEmittedFns; 0083 0084 /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current 0085 /// context is "used as device code". 0086 /// 0087 /// - If CurContext is a __host__ function, does not emit any diagnostics 0088 /// unless \p EmitOnBothSides is true. 0089 /// - If CurContext is a __device__ or __global__ function, emits the 0090 /// diagnostics immediately. 0091 /// - If CurContext is a __host__ __device__ function and we are compiling for 0092 /// the device, creates a diagnostic which is emitted if and when we realize 0093 /// that the function will be codegen'ed. 0094 /// 0095 /// Example usage: 0096 /// 0097 /// // Variable-length arrays are not allowed in CUDA device code. 0098 /// if (DiagIfDeviceCode(Loc, diag::err_cuda_vla) << CurrentTarget()) 0099 /// return ExprError(); 0100 /// // Otherwise, continue parsing as normal. 0101 SemaDiagnosticBuilder DiagIfDeviceCode(SourceLocation Loc, unsigned DiagID); 0102 0103 /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current 0104 /// context is "used as host code". 0105 /// 0106 /// Same as DiagIfDeviceCode, with "host" and "device" switched. 0107 SemaDiagnosticBuilder DiagIfHostCode(SourceLocation Loc, unsigned DiagID); 0108 0109 /// Determines whether the given function is a CUDA device/host/kernel/etc. 0110 /// function. 0111 /// 0112 /// Use this rather than examining the function's attributes yourself -- you 0113 /// will get it wrong. Returns CUDAFunctionTarget::Host if D is null. 0114 CUDAFunctionTarget IdentifyTarget(const FunctionDecl *D, 0115 bool IgnoreImplicitHDAttr = false); 0116 CUDAFunctionTarget IdentifyTarget(const ParsedAttributesView &Attrs); 0117 0118 enum CUDAVariableTarget { 0119 CVT_Device, /// Emitted on device side with a shadow variable on host side 0120 CVT_Host, /// Emitted on host side only 0121 CVT_Both, /// Emitted on both sides with different addresses 0122 CVT_Unified, /// Emitted as a unified address, e.g. managed variables 0123 }; 0124 /// Determines whether the given variable is emitted on host or device side. 0125 CUDAVariableTarget IdentifyTarget(const VarDecl *D); 0126 0127 /// Defines kinds of CUDA global host/device context where a function may be 0128 /// called. 0129 enum CUDATargetContextKind { 0130 CTCK_Unknown, /// Unknown context 0131 CTCK_InitGlobalVar, /// Function called during global variable 0132 /// initialization 0133 }; 0134 0135 /// Define the current global CUDA host/device context where a function may be 0136 /// called. Only used when a function is called outside of any functions. 0137 struct CUDATargetContext { 0138 CUDAFunctionTarget Target = CUDAFunctionTarget::HostDevice; 0139 CUDATargetContextKind Kind = CTCK_Unknown; 0140 Decl *D = nullptr; 0141 } CurCUDATargetCtx; 0142 0143 struct CUDATargetContextRAII { 0144 SemaCUDA &S; 0145 SemaCUDA::CUDATargetContext SavedCtx; 0146 CUDATargetContextRAII(SemaCUDA &S_, SemaCUDA::CUDATargetContextKind K, 0147 Decl *D); 0148 ~CUDATargetContextRAII() { S.CurCUDATargetCtx = SavedCtx; } 0149 }; 0150 0151 /// Gets the CUDA target for the current context. 0152 CUDAFunctionTarget CurrentTarget() { 0153 return IdentifyTarget(dyn_cast<FunctionDecl>(SemaRef.CurContext)); 0154 } 0155 0156 static bool isImplicitHostDeviceFunction(const FunctionDecl *D); 0157 0158 // CUDA function call preference. Must be ordered numerically from 0159 // worst to best. 0160 enum CUDAFunctionPreference { 0161 CFP_Never, // Invalid caller/callee combination. 0162 CFP_WrongSide, // Calls from host-device to host or device 0163 // function that do not match current compilation 0164 // mode. 0165 CFP_HostDevice, // Any calls to host/device functions. 0166 CFP_SameSide, // Calls from host-device to host or device 0167 // function matching current compilation mode. 0168 CFP_Native, // host-to-host or device-to-device calls. 0169 }; 0170 0171 /// Identifies relative preference of a given Caller/Callee 0172 /// combination, based on their host/device attributes. 0173 /// \param Caller function which needs address of \p Callee. 0174 /// nullptr in case of global context. 0175 /// \param Callee target function 0176 /// 0177 /// \returns preference value for particular Caller/Callee combination. 0178 CUDAFunctionPreference IdentifyPreference(const FunctionDecl *Caller, 0179 const FunctionDecl *Callee); 0180 0181 /// Determines whether Caller may invoke Callee, based on their CUDA 0182 /// host/device attributes. Returns false if the call is not allowed. 0183 /// 0184 /// Note: Will return true for CFP_WrongSide calls. These may appear in 0185 /// semantically correct CUDA programs, but only if they're never codegen'ed. 0186 bool IsAllowedCall(const FunctionDecl *Caller, const FunctionDecl *Callee) { 0187 return IdentifyPreference(Caller, Callee) != CFP_Never; 0188 } 0189 0190 /// May add implicit CUDAHostAttr and CUDADeviceAttr attributes to FD, 0191 /// depending on FD and the current compilation settings. 0192 void maybeAddHostDeviceAttrs(FunctionDecl *FD, const LookupResult &Previous); 0193 0194 /// May add implicit CUDAConstantAttr attribute to VD, depending on VD 0195 /// and current compilation settings. 0196 void MaybeAddConstantAttr(VarDecl *VD); 0197 0198 /// Check whether we're allowed to call Callee from the current context. 0199 /// 0200 /// - If the call is never allowed in a semantically-correct program 0201 /// (CFP_Never), emits an error and returns false. 0202 /// 0203 /// - If the call is allowed in semantically-correct programs, but only if 0204 /// it's never codegen'ed (CFP_WrongSide), creates a deferred diagnostic to 0205 /// be emitted if and when the caller is codegen'ed, and returns true. 0206 /// 0207 /// Will only create deferred diagnostics for a given SourceLocation once, 0208 /// so you can safely call this multiple times without generating duplicate 0209 /// deferred errors. 0210 /// 0211 /// - Otherwise, returns true without emitting any diagnostics. 0212 bool CheckCall(SourceLocation Loc, FunctionDecl *Callee); 0213 0214 void CheckLambdaCapture(CXXMethodDecl *D, const sema::Capture &Capture); 0215 0216 /// Set __device__ or __host__ __device__ attributes on the given lambda 0217 /// operator() method. 0218 /// 0219 /// CUDA lambdas by default is host device function unless it has explicit 0220 /// host or device attribute. 0221 void SetLambdaAttrs(CXXMethodDecl *Method); 0222 0223 /// Record \p FD if it is a CUDA/HIP implicit host device function used on 0224 /// device side in device compilation. 0225 void RecordImplicitHostDeviceFuncUsedByDevice(const FunctionDecl *FD); 0226 0227 /// Finds a function in \p Matches with highest calling priority 0228 /// from \p Caller context and erases all functions with lower 0229 /// calling priority. 0230 void EraseUnwantedMatches( 0231 const FunctionDecl *Caller, 0232 llvm::SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> 0233 &Matches); 0234 0235 /// Given a implicit special member, infer its CUDA target from the 0236 /// calls it needs to make to underlying base/field special members. 0237 /// \param ClassDecl the class for which the member is being created. 0238 /// \param CSM the kind of special member. 0239 /// \param MemberDecl the special member itself. 0240 /// \param ConstRHS true if this is a copy operation with a const object on 0241 /// its RHS. 0242 /// \param Diagnose true if this call should emit diagnostics. 0243 /// \return true if there was an error inferring. 0244 /// The result of this call is implicit CUDA target attribute(s) attached to 0245 /// the member declaration. 0246 bool inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, 0247 CXXSpecialMemberKind CSM, 0248 CXXMethodDecl *MemberDecl, 0249 bool ConstRHS, bool Diagnose); 0250 0251 /// \return true if \p CD can be considered empty according to CUDA 0252 /// (E.2.3.1 in CUDA 7.5 Programming guide). 0253 bool isEmptyConstructor(SourceLocation Loc, CXXConstructorDecl *CD); 0254 bool isEmptyDestructor(SourceLocation Loc, CXXDestructorDecl *CD); 0255 0256 // \brief Checks that initializers of \p Var satisfy CUDA restrictions. In 0257 // case of error emits appropriate diagnostic and invalidates \p Var. 0258 // 0259 // \details CUDA allows only empty constructors as initializers for global 0260 // variables (see E.2.3.1, CUDA 7.5). The same restriction also applies to all 0261 // __shared__ variables whether they are local or not (they all are implicitly 0262 // static in CUDA). One exception is that CUDA allows constant initializers 0263 // for __constant__ and __device__ variables. 0264 void checkAllowedInitializer(VarDecl *VD); 0265 0266 /// Check whether NewFD is a valid overload for CUDA. Emits 0267 /// diagnostics and invalidates NewFD if not. 0268 void checkTargetOverload(FunctionDecl *NewFD, const LookupResult &Previous); 0269 /// Copies target attributes from the template TD to the function FD. 0270 void inheritTargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD); 0271 0272 /// Returns the name of the launch configuration function. This is the name 0273 /// of the function that will be called to configure kernel call, with the 0274 /// parameters specified via <<<>>>. 0275 std::string getConfigureFuncName() const; 0276 0277 private: 0278 unsigned ForceHostDeviceDepth = 0; 0279 0280 friend class ASTReader; 0281 friend class ASTWriter; 0282 }; 0283 0284 } // namespace clang 0285 0286 namespace llvm { 0287 // Hash a FunctionDeclAndLoc by looking at both its FunctionDecl and its 0288 // SourceLocation. 0289 template <> struct DenseMapInfo<clang::SemaCUDA::FunctionDeclAndLoc> { 0290 using FunctionDeclAndLoc = clang::SemaCUDA::FunctionDeclAndLoc; 0291 using FDBaseInfo = 0292 DenseMapInfo<clang::CanonicalDeclPtr<const clang::FunctionDecl>>; 0293 0294 static FunctionDeclAndLoc getEmptyKey() { 0295 return {FDBaseInfo::getEmptyKey(), clang::SourceLocation()}; 0296 } 0297 0298 static FunctionDeclAndLoc getTombstoneKey() { 0299 return {FDBaseInfo::getTombstoneKey(), clang::SourceLocation()}; 0300 } 0301 0302 static unsigned getHashValue(const FunctionDeclAndLoc &FDL) { 0303 return hash_combine(FDBaseInfo::getHashValue(FDL.FD), 0304 FDL.Loc.getHashValue()); 0305 } 0306 0307 static bool isEqual(const FunctionDeclAndLoc &LHS, 0308 const FunctionDeclAndLoc &RHS) { 0309 return LHS.FD == RHS.FD && LHS.Loc == RHS.Loc; 0310 } 0311 }; 0312 } // namespace llvm 0313 0314 #endif // LLVM_CLANG_SEMA_SEMACUDA_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|