|
18 | 18 | #include "clang/Basic/TargetInfo.h" |
19 | 19 | #include "clang/Lex/Preprocessor.h" |
20 | 20 | #include "clang/Sema/Lookup.h" |
| 21 | +#include "clang/Sema/Overload.h" |
21 | 22 | #include "clang/Sema/ScopeInfo.h" |
22 | 23 | #include "clang/Sema/Sema.h" |
23 | 24 | #include "clang/Sema/Template.h" |
@@ -1100,3 +1101,49 @@ std::string SemaCUDA::getConfigureFuncName() const { |
1100 | 1101 | // Legacy CUDA kernel configuration call |
1101 | 1102 | return "cudaConfigureCall"; |
1102 | 1103 | } |
| 1104 | + |
| 1105 | +// Record any local constexpr variables that are passed one way on the host |
| 1106 | +// and another on the device. |
| 1107 | +void SemaCUDA::recordPotentialODRUsedVariable( |
| 1108 | + MultiExprArg Arguments, OverloadCandidateSet &Candidates) { |
| 1109 | + sema::LambdaScopeInfo *LambdaInfo = SemaRef.getCurLambda(); |
| 1110 | + if (!LambdaInfo) |
| 1111 | + return; |
| 1112 | + |
| 1113 | + for (unsigned I = 0; I < Arguments.size(); ++I) { |
| 1114 | + auto *DeclRef = dyn_cast<DeclRefExpr>(Arguments[I]); |
| 1115 | + if (!DeclRef) |
| 1116 | + continue; |
| 1117 | + auto *Variable = dyn_cast<VarDecl>(DeclRef->getDecl()); |
| 1118 | + if (!Variable || !Variable->isLocalVarDecl() || !Variable->isConstexpr()) |
| 1119 | + continue; |
| 1120 | + |
| 1121 | + bool HostByValue = false, HostByRef = false; |
| 1122 | + bool DeviceByValue = false, DeviceByRef = false; |
| 1123 | + |
| 1124 | + for (OverloadCandidate &Candidate : Candidates) { |
| 1125 | + FunctionDecl *Callee = Candidate.Function; |
| 1126 | + if (!Callee || I >= Callee->getNumParams()) |
| 1127 | + continue; |
| 1128 | + |
| 1129 | + CUDAFunctionTarget Target = IdentifyTarget(Callee); |
| 1130 | + if (Target == CUDAFunctionTarget::InvalidTarget || |
| 1131 | + Target == CUDAFunctionTarget::Global) |
| 1132 | + continue; |
| 1133 | + |
| 1134 | + bool CoversHost = (Target == CUDAFunctionTarget::Host || |
| 1135 | + Target == CUDAFunctionTarget::HostDevice); |
| 1136 | + bool CoversDevice = (Target == CUDAFunctionTarget::Device || |
| 1137 | + Target == CUDAFunctionTarget::HostDevice); |
| 1138 | + |
| 1139 | + bool IsRef = Callee->getParamDecl(I)->getType()->isReferenceType(); |
| 1140 | + HostByValue |= CoversHost && !IsRef; |
| 1141 | + HostByRef |= CoversHost && IsRef; |
| 1142 | + DeviceByValue |= CoversDevice && !IsRef; |
| 1143 | + DeviceByRef |= CoversDevice && IsRef; |
| 1144 | + } |
| 1145 | + |
| 1146 | + if ((HostByValue && DeviceByRef) || (HostByRef && DeviceByValue)) |
| 1147 | + LambdaInfo->CUDAPotentialODRUsedVars.insert(Variable); |
| 1148 | + } |
| 1149 | +} |
0 commit comments