summaryrefslogtreecommitdiff
path: root/lib/CodeGen/StackSlotColoring.cpp
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2010-05-25 21:44:26 +0000
committerBill Wendling <isanbard@gmail.com>2010-05-25 21:44:26 +0000
commit5edfbdc9635405fe601d6d4645443d3a38c5e7b7 (patch)
treeaa77fa5fdeb6487d133a82d1def78a0bb755a30d /lib/CodeGen/StackSlotColoring.cpp
parent02b46bc9426925b90137d264216a54aa413335fd (diff)
downloadllvm-5edfbdc9635405fe601d6d4645443d3a38c5e7b7.tar.gz
llvm-5edfbdc9635405fe601d6d4645443d3a38c5e7b7.tar.bz2
llvm-5edfbdc9635405fe601d6d4645443d3a38c5e7b7.tar.xz
Okay, bear with me here...
If you have a setjmp/longjmp situation, it's possible for stack slot coloring to reuse a stack slot before it's really dead. For instance, if we have something like this: 1: y = g; x = sigsetjmp(env, 0); switch (x) { case 1: /* ... */ goto run; case 0: run: do_run(); /* marked as "no return" */ break; case 3: if (...) { /* ... */ goto run; } /* ... */ break; } 2: g = y; "y" may be put onto the stack, so the expression "g = y" is relying upon the fact that the stack slot containing "y" isn't modified between (1) and (2). But it can be, because of the "no return" calls in there. A longjmp might come back with 3, modify the stack slot, and then go to case 0. And it's perfectly acceptable to reuse the stack slot there because there's no CFG flow from case 3 to (2). The fix is to disable certain optimizations in these situations. Ideally, we'd disable them for all "returns twice" functions. But we don't support that attribute. Check for "setjmp" and "sigsetjmp" instead. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@104640 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/StackSlotColoring.cpp')
-rw-r--r--lib/CodeGen/StackSlotColoring.cpp41
1 files changed, 41 insertions, 0 deletions
diff --git a/lib/CodeGen/StackSlotColoring.cpp b/lib/CodeGen/StackSlotColoring.cpp
index 13d608692a..fc941df8d9 100644
--- a/lib/CodeGen/StackSlotColoring.cpp
+++ b/lib/CodeGen/StackSlotColoring.cpp
@@ -13,6 +13,8 @@
#define DEBUG_TYPE "stackcoloring"
#include "VirtRegMap.h"
+#include "llvm/Function.h"
+#include "llvm/Module.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/LiveStackAnalysis.h"
@@ -116,6 +118,7 @@ namespace {
private:
void InitializeSlots();
+ bool CheckForSetJmpCall(const MachineFunction &MF);
void ScanForSpillSlotRefs(MachineFunction &MF);
bool OverlapWithAssignments(LiveInterval *li, int Color) const;
int ColorSlot(LiveInterval *li);
@@ -159,6 +162,34 @@ namespace {
};
}
+/// CheckForSetJmpCall - Return true if there's a call to setjmp/sigsetjmp in
+/// this function.
+bool StackSlotColoring::CheckForSetJmpCall(const MachineFunction &MF) {
+ const Function *F = MF.getFunction();
+ const Module *M = F->getParent();
+ const Function *SetJmp = M->getFunction("setjmp");
+ const Function *SigSetJmp = M->getFunction("sigsetjmp");
+
+ if (!SetJmp && !SigSetJmp)
+ return false;
+
+ if (SetJmp && !SetJmp->use_empty())
+ for (Value::const_use_iterator
+ I = SetJmp->use_begin(), E = SetJmp->use_end(); I != E; ++I)
+ if (const CallInst *CI = dyn_cast<CallInst>(I))
+ if (CI->getParent()->getParent() == F)
+ return true;
+
+ if (SigSetJmp && !SigSetJmp->use_empty())
+ for (Value::const_use_iterator
+ I = SigSetJmp->use_begin(), E = SigSetJmp->use_end(); I != E; ++I)
+ if (const CallInst *CI = dyn_cast<CallInst>(I))
+ if (CI->getParent()->getParent() == F)
+ return true;
+
+ return false;
+}
+
/// ScanForSpillSlotRefs - Scan all the machine instructions for spill slot
/// references and update spill slot weights.
void StackSlotColoring::ScanForSpillSlotRefs(MachineFunction &MF) {
@@ -722,6 +753,16 @@ bool StackSlotColoring::runOnMachineFunction(MachineFunction &MF) {
return false;
}
+ // If there are calls to setjmp or sigsetjmp, don't perform stack slot
+ // coloring. The stack could be modified before the longjmp is executed,
+ // resulting in the wrong value being used afterwards. (See
+ // <rdar://problem/8007500>.)
+ //
+ // FIXME: This goes beyond the setjmp/sigsetjmp functions. Ideally, we should
+ // check for the GCC "returns twice" attribute.
+ if (CheckForSetJmpCall(MF))
+ return false;
+
// Gather spill slot references
ScanForSpillSlotRefs(MF);
InitializeSlots();