summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2009-05-04 16:50:29 +0000
committerDuncan Sands <baldrick@free.fr>2009-05-04 16:50:29 +0000
commit50c70336b0e30c94384ecfb65b85dc1a95d99e40 (patch)
tree7ee40c5f99b102494b66bc71c5bc353141fbc2aa /llvm/lib
parentb88227ef4c78b1ce0e0b3aede39261587ef8e98a (diff)
downloadbcm5719-llvm-50c70336b0e30c94384ecfb65b85dc1a95d99e40.tar.gz
bcm5719-llvm-50c70336b0e30c94384ecfb65b85dc1a95d99e40.zip
Teach capture tracking that readonly functions can
only capture their arguments by returning them or throwing an exception or not based on the argument value. Patch essentially by Frits van Bommel. llvm-svn: 70876
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/CaptureTracking.cpp75
1 files changed, 47 insertions, 28 deletions
diff --git a/llvm/lib/Analysis/CaptureTracking.cpp b/llvm/lib/Analysis/CaptureTracking.cpp
index ceb964619c5..773f53d2cd2 100644
--- a/llvm/lib/Analysis/CaptureTracking.cpp
+++ b/llvm/lib/Analysis/CaptureTracking.cpp
@@ -49,11 +49,7 @@ bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures) {
switch (I->getOpcode()) {
case Instruction::Call:
case Instruction::Invoke: {
- CallSite CS = CallSite::get(I);
- // Not captured if the callee is readonly and doesn't return a copy
- // through its return value.
- if (CS.onlyReadsMemory() && I->getType() == Type::VoidTy)
- break;
+ CallSite CS(I);
// Not captured if only passed via 'nocapture' arguments. Note that
// calling a function pointer does not in itself cause the pointer to
@@ -62,46 +58,69 @@ bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures) {
// that loading a value from a pointer does not cause the pointer to be
// captured, even though the loaded value might be the pointer itself
// (think of self-referential objects).
+ bool MayBeCaptured = false;
CallSite::arg_iterator B = CS.arg_begin(), E = CS.arg_end();
for (CallSite::arg_iterator A = B; A != E; ++A)
- if (A->get() == V && !CS.paramHasAttr(A - B + 1, Attribute::NoCapture))
- // The parameter is not marked 'nocapture' - captured.
- return true;
- // Only passed via 'nocapture' arguments, or is the called function - not
- // captured.
+ if (A->get() == V && !CS.paramHasAttr(A-B+1, Attribute::NoCapture)) {
+ // The parameter is not marked 'nocapture' - handled by generic code
+ // below.
+ MayBeCaptured = true;
+ break;
+ }
+ if (!MayBeCaptured)
+ // Only passed via 'nocapture' arguments, or is the called function -
+ // not captured.
+ continue;
+ if (!CS.doesNotThrow())
+ // Even a readonly function can leak bits by throwing an exception or
+ // not depending on the input value.
+ return true;
+ // Fall through to the generic code.
break;
}
case Instruction::Free:
// Freeing a pointer does not cause it to be captured.
- break;
+ continue;
case Instruction::Load:
// Loading from a pointer does not cause it to be captured.
- break;
+ continue;
case Instruction::Ret:
if (ReturnCaptures)
return true;
- break;
+ continue;
case Instruction::Store:
if (V == I->getOperand(0))
// Stored the pointer - it may be captured.
return true;
// Storing to the pointee does not cause the pointer to be captured.
- break;
- case Instruction::BitCast:
- case Instruction::GetElementPtr:
- case Instruction::PHI:
- case Instruction::Select:
- // The original value is not captured via this if the new value isn't.
- for (Instruction::use_iterator UI = I->use_begin(), UE = I->use_end();
- UI != UE; ++UI) {
- Use *U = &UI.getUse();
- if (Visited.insert(U))
- Worklist.push_back(U);
- }
- break;
- default:
- // Something else - be conservative and say it is captured.
+ continue;
+ }
+
+ // If it may write to memory and isn't one of the special cases above,
+ // be conservative and assume the pointer is captured.
+ if (I->mayWriteToMemory())
return true;
+
+ // If the instruction doesn't write memory, it can only capture by
+ // having its own value depend on the input value.
+ const Type* Ty = I->getType();
+ if (Ty == Type::VoidTy)
+ // The value of an instruction can't be a copy if it can't contain any
+ // information.
+ continue;
+ if (!isa<PointerType>(Ty))
+ // At the moment, we don't track non-pointer values, so be conservative
+ // and assume the pointer is captured.
+ // FIXME: Track these too. This would need to be done very carefully as
+ // it is easy to leak bits via control flow if integer values are allowed.
+ return true;
+
+ // The original value is not captured via this if the new value isn't.
+ for (Instruction::use_iterator UI = I->use_begin(), UE = I->use_end();
+ UI != UE; ++UI) {
+ Use *U = &UI.getUse();
+ if (Visited.insert(U))
+ Worklist.push_back(U);
}
}
OpenPOWER on IntegriCloud