|
17 | 17 | #include "llvm/ADT/SmallPtrSet.h"
|
18 | 18 | #include "llvm/ADT/Statistic.h"
|
19 | 19 | #include "llvm/Analysis/BranchProbabilityInfo.h"
|
20 |
| -#include "llvm/Analysis/CaptureTracking.h" |
21 | 20 | #include "llvm/Analysis/EHPersonalities.h"
|
22 | 21 | #include "llvm/Analysis/OptimizationRemarkEmitter.h"
|
23 | 22 | #include "llvm/CodeGen/Passes.h"
|
@@ -157,6 +156,41 @@ bool StackProtector::ContainsProtectableArray(Type *Ty, bool &IsLarge,
|
157 | 156 | return NeedsProtector;
|
158 | 157 | }
|
159 | 158 |
|
| 159 | +bool StackProtector::HasAddressTaken(const Instruction *AI, |
| 160 | + SmallPtrSetImpl<const PHINode *> &VisitedPHIs) { |
| 161 | + for (const User *U : AI->users()) { |
| 162 | + if (const StoreInst *SI = dyn_cast<StoreInst>(U)) { |
| 163 | + if (AI == SI->getValueOperand()) |
| 164 | + return true; |
| 165 | + } else if (const PtrToIntInst *SI = dyn_cast<PtrToIntInst>(U)) { |
| 166 | + if (AI == SI->getOperand(0)) |
| 167 | + return true; |
| 168 | + } else if (const CallInst *CI = dyn_cast<CallInst>(U)) { |
| 169 | + // Ignore intrinsics that are not calls. TODO: Use isLoweredToCall(). |
| 170 | + if (!isa<DbgInfoIntrinsic>(CI) && !CI->isLifetimeStartOrEnd()) |
| 171 | + return true; |
| 172 | + } else if (isa<InvokeInst>(U)) { |
| 173 | + return true; |
| 174 | + } else if (const SelectInst *SI = dyn_cast<SelectInst>(U)) { |
| 175 | + if (HasAddressTaken(SI, VisitedPHIs)) |
| 176 | + return true; |
| 177 | + } else if (const PHINode *PN = dyn_cast<PHINode>(U)) { |
| 178 | + // Keep track of what PHI nodes we have already visited to ensure |
| 179 | + // they are only visited once. |
| 180 | + if (VisitedPHIs.insert(PN).second) |
| 181 | + if (HasAddressTaken(PN, VisitedPHIs)) |
| 182 | + return true; |
| 183 | + } else if (const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) { |
| 184 | + if (HasAddressTaken(GEP, VisitedPHIs)) |
| 185 | + return true; |
| 186 | + } else if (const BitCastInst *BI = dyn_cast<BitCastInst>(U)) { |
| 187 | + if (HasAddressTaken(BI, VisitedPHIs)) |
| 188 | + return true; |
| 189 | + } |
| 190 | + } |
| 191 | + return false; |
| 192 | +} |
| 193 | + |
160 | 194 | /// Search for the first call to the llvm.stackprotector intrinsic and return it
|
161 | 195 | /// if present.
|
162 | 196 | static const CallInst *findStackProtectorIntrinsic(Function &F) {
|
@@ -211,6 +245,12 @@ bool StackProtector::RequiresStackProtector() {
|
211 | 245 | else if (!F->hasFnAttribute(Attribute::StackProtect))
|
212 | 246 | return false;
|
213 | 247 |
|
| 248 | + /// VisitedPHIs - The set of PHI nodes visited when determining |
| 249 | + /// if a variable's reference has been taken. This set |
| 250 | + /// is maintained to ensure we don't visit the same PHI node multiple |
| 251 | + /// times. |
| 252 | + SmallPtrSet<const PHINode *, 16> VisitedPHIs; |
| 253 | + |
214 | 254 | for (const BasicBlock &BB : *F) {
|
215 | 255 | for (const Instruction &I : BB) {
|
216 | 256 | if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
|
@@ -264,9 +304,7 @@ bool StackProtector::RequiresStackProtector() {
|
264 | 304 | continue;
|
265 | 305 | }
|
266 | 306 |
|
267 |
| - if (Strong && PointerMayBeCaptured(AI, |
268 |
| - /* ReturnCaptures */ false, |
269 |
| - /* StoreCaptures */ true)) { |
| 307 | + if (Strong && HasAddressTaken(AI, VisitedPHIs)) { |
270 | 308 | ++NumAddrTaken;
|
271 | 309 | Layout.insert(std::make_pair(AI, MachineFrameInfo::SSPLK_AddrOf));
|
272 | 310 | ORE.emit([&]() {
|
|
0 commit comments