diff options
author | Reid Kleckner <reid@kleckner.net> | 2013-12-10 05:12:23 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2013-12-10 05:12:23 +0000 |
commit | ec4d326aad404fa7a6335aadcc21710ecc6a63b0 (patch) | |
tree | 6a359376b8e93694f111bc7edbdc902470b22929 /lib/Target/X86/X86RegisterInfo.cpp | |
parent | e15c1079cb4942f8975cf318b5deb87ed31c250a (diff) | |
download | llvm-ec4d326aad404fa7a6335aadcc21710ecc6a63b0.tar.gz llvm-ec4d326aad404fa7a6335aadcc21710ecc6a63b0.tar.bz2 llvm-ec4d326aad404fa7a6335aadcc21710ecc6a63b0.tar.xz |
Fix miscompile of MS inline assembly with stack realignment
For stack frames requiring realignment, three pointers may be needed:
- ebp to address incoming arguments
- esi (could be any callee-saved register) to address locals
- esp to address outgoing arguments
We would use esi unconditionally without verifying that it did not
conflict with inline assembly.
This change doesn't do the verification, it simply emits a fatal error
on functions that use stack realignment, dynamic SP adjustments, and
inline assembly.
Because stack realignment is common on Windows, we also no longer assume
that MS inline assembly clobbers esp. Instead, we analyze the inline
instructions for implicit definitions and check if esp is there. If so,
we require the use of a base pointer and consider it in the condition
above.
Mostly fixes PR16830, but we could try harder to find a non-conflicting
base pointer.
Reviewers: sunfish
Differential Revision: http://llvm-reviews.chandlerc.com/D1317
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@196876 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/X86/X86RegisterInfo.cpp')
-rw-r--r-- | lib/Target/X86/X86RegisterInfo.cpp | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index dbda556b1b..d3d05cd83a 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -347,6 +347,12 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const { "Stack realignment in presence of dynamic allocas is not supported with" "this calling convention."); + // FIXME: Do a proper analysis of the inline asm to see if it actually + // conflicts with the base register we chose. + if (MF.hasInlineAsm()) + report_fatal_error("Stack realignment in presence of dynamic stack " + "adjustments is not supported with inline assembly."); + for (MCSubRegIterator I(getBaseRegister(), this, /*IncludeSelf=*/true); I.isValid(); ++I) Reserved.set(*I); @@ -403,18 +409,15 @@ bool X86RegisterInfo::hasBasePointer(const MachineFunction &MF) const { if (!EnableBasePointer) return false; - // When we need stack realignment and there are dynamic allocas, we can't - // reference off of the stack pointer, so we reserve a base pointer. - // - // This is also true if the function contain MS-style inline assembly. We - // do this because if any stack changes occur in the inline assembly, e.g., - // "pusha", then any C local variable or C argument references in the - // inline assembly will be wrong because the SP is not properly tracked. - if ((needsStackRealignment(MF) && MFI->hasVarSizedObjects()) || - MF.hasMSInlineAsm()) - return true; - - return false; + // When we need stack realignment, we can't address the stack from the frame + // pointer. When we have dynamic allocas or stack-adjusting inline asm, we + // can't address variables from the stack pointer. MS inline asm can + // reference locals while also adjusting the stack pointer. When we can't + // use both the SP and the FP, we need a separate base pointer register. + bool CantUseFP = needsStackRealignment(MF); + bool CantUseSP = + MFI->hasVarSizedObjects() || MFI->hasInlineAsmWithSPAdjust(); + return CantUseFP && CantUseSP; } bool X86RegisterInfo::canRealignStack(const MachineFunction &MF) const { |