diff options
author | Duncan Sands <baldrick@free.fr> | 2009-05-04 16:50:29 +0000 |
---|---|---|
committer | Duncan Sands <baldrick@free.fr> | 2009-05-04 16:50:29 +0000 |
commit | 50c70336b0e30c94384ecfb65b85dc1a95d99e40 (patch) | |
tree | 7ee40c5f99b102494b66bc71c5bc353141fbc2aa /llvm/lib/Analysis | |
parent | b88227ef4c78b1ce0e0b3aede39261587ef8e98a (diff) | |
download | bcm5719-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/Analysis')
-rw-r--r-- | llvm/lib/Analysis/CaptureTracking.cpp | 75 |
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); } } |