summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2011-07-13 21:29:53 +0000
committerEli Friedman <eli.friedman@gmail.com>2011-07-13 21:29:53 +0000
commit344ec7971547d922be35e54c5f565b8fdd0fe04e (patch)
treeb244d76cc96e75099cbe873b288b89f9e7227a61 /llvm/lib
parentf0335ce632e8c828e4bf6f5e50672c5a035b7ccd (diff)
downloadbcm5719-llvm-344ec7971547d922be35e54c5f565b8fdd0fe04e.tar.gz
bcm5719-llvm-344ec7971547d922be35e54c5f565b8fdd0fe04e.zip
Make sure we don't combine a large displacement and a frame index in the same addressing mode on x86-64. It can overflow, leading to a crash/miscompile.
<rdar://problem/9763308> llvm-svn: 135084
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/X86/X86ISelDAGToDAG.cpp33
1 files changed, 25 insertions, 8 deletions
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index b617e976314..2b0f283bec7 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -548,17 +548,33 @@ void X86DAGToDAGISel::EmitFunctionEntryCode() {
EmitSpecialCodeForMain(MF->begin(), MF->getFrameInfo());
}
+static bool isDispSafeForFrameIndex(int64_t Val) {
+ // On 64-bit platforms, we can run into an issue where a frame index
+ // includes a displacement that, when added to the explicit displacement,
+ // will overflow the displacement field. Assuming that the frame index
+ // displacement fits into a 31-bit integer (which is only slightly more
+ // aggressive than the current fundamental assumption that it fits into
+ // a 32-bit integer), a 31-bit disp should always be safe.
+ return isInt<31>(Val);
+}
+
bool X86DAGToDAGISel::FoldOffsetIntoAddress(uint64_t Offset,
X86ISelAddressMode &AM) {
int64_t Val = AM.Disp + Offset;
CodeModel::Model M = TM.getCodeModel();
- if (!Subtarget->is64Bit() ||
- X86::isOffsetSuitableForCodeModel(Val, M,
- AM.hasSymbolicDisplacement())) {
- AM.Disp = Val;
- return false;
+ if (Subtarget->is64Bit()) {
+ if (!X86::isOffsetSuitableForCodeModel(Val, M,
+ AM.hasSymbolicDisplacement()))
+ return true;
+ // In addition to the checks required for a register base, check that
+ // we do not try to use an unsafe Disp with a frame index.
+ if (AM.BaseType == X86ISelAddressMode::FrameIndexBase &&
+ !isDispSafeForFrameIndex(Val))
+ return true;
}
- return true;
+ AM.Disp = Val;
+ return false;
+
}
bool X86DAGToDAGISel::MatchLoadInAddress(LoadSDNode *N, X86ISelAddressMode &AM){
@@ -751,8 +767,9 @@ bool X86DAGToDAGISel::MatchAddressRecursively(SDValue N, X86ISelAddressMode &AM,
break;
case ISD::FrameIndex:
- if (AM.BaseType == X86ISelAddressMode::RegBase
- && AM.Base_Reg.getNode() == 0) {
+ if (AM.BaseType == X86ISelAddressMode::RegBase &&
+ AM.Base_Reg.getNode() == 0 &&
+ (!Subtarget->is64Bit() || isDispSafeForFrameIndex(AM.Disp))) {
AM.BaseType = X86ISelAddressMode::FrameIndexBase;
AM.Base_FrameIndex = cast<FrameIndexSDNode>(N)->getIndex();
return false;
OpenPOWER on IntegriCloud