diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2011-07-13 21:29:53 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2011-07-13 21:29:53 +0000 |
commit | 344ec7971547d922be35e54c5f565b8fdd0fe04e (patch) | |
tree | b244d76cc96e75099cbe873b288b89f9e7227a61 /llvm/lib | |
parent | f0335ce632e8c828e4bf6f5e50672c5a035b7ccd (diff) | |
download | bcm5719-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.cpp | 33 |
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; |