[cfe-commits] r64014 - in /cfe/trunk/lib/CodeGen: CGDecl.cpp CGObjC.cpp CGStmt.cpp CodeGenFunction.cpp CodeGenFunction.h
Mike Stump
mrs at apple.com
Sat Feb 7 04:52:27 PST 2009
Author: mrs
Date: Sat Feb 7 06:52:26 2009
New Revision: 64014
URL: http://llvm.org/viewvc/llvm-project?rev=64014&view=rev
Log:
Fixup goto codegen in and around VLAs.
Modified:
cfe/trunk/lib/CodeGen/CGDecl.cpp
cfe/trunk/lib/CodeGen/CGObjC.cpp
cfe/trunk/lib/CodeGen/CGStmt.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=64014&r1=64013&r2=64014&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Sat Feb 7 06:52:26 2009
@@ -188,7 +188,7 @@
Builder.CreateStore(V, Stack);
- StackSaveValues.back() = Stack;
+ StackSaveValues.back() = StackDepth = Stack;
}
// Get the element type.
const llvm::Type *LElemTy = ConvertType(Ty);
Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=64014&r1=64013&r2=64014&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Sat Feb 7 06:52:26 2009
@@ -515,8 +515,7 @@
llvm::BasicBlock *LoopEnd = createBasicBlock("loopend");
llvm::BasicBlock *AfterBody = createBasicBlock("afterbody");
- BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody,
- ObjCEHStack.size()));
+ BreakContinuePush(LoopEnd, AfterBody);
EmitStmt(S.getBody());
Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=64014&r1=64013&r2=64014&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Sat Feb 7 06:52:26 2009
@@ -164,6 +164,7 @@
}
if (llvm::Value *V = StackSaveValues.pop_back_val()) {
+ StackDepth = V;
V = Builder.CreateLoad(V, "tmp");
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stackrestore);
@@ -186,6 +187,41 @@
Builder.SetInsertPoint(BB);
}
+void CodeGenFunction::EmitStackUpdate(const LabelStmt &S) {
+ if (StackDepthMap.find(&S) == StackDepthMap.end()) {
+ // If we can't find it, just remember the depth now,
+ // so we can validate it later.
+ // FIXME: We need to save a place to insert the adjustment,
+ // if needed, here, sa that later in EmitLabel, we can
+ // backpatch the adjustment into that place, instead of
+ // saying unsupported.
+ StackDepthMap[&S] = StackDepth;
+ return;
+ }
+
+ // Find applicable stack depth, if any...
+ llvm::Value *V = StackDepthMap[&S];
+ // V can be 0 here, if it is, be sure to start searching from the
+ // top of the function, as we want the next save after that point.
+ for (unsigned int i = 0; i < StackSaveValues.size(); ++i)
+ if (StackSaveValues[i] == V) {
+ // The actual depth is actually in the next used slot, if any.
+ while (++i < StackSaveValues.size()
+ && (V = StackSaveValues[i]) == 0) ;
+ // If there were no other depth changes, we don't need any
+ // adjustments.
+ if (V) {
+ V = Builder.CreateLoad(V, "tmp");
+ // and restore it.
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stackrestore);
+ Builder.CreateCall(F, V);
+ }
+ } else
+ // FIXME: Move to semq and assert here, codegen isn't the right
+ // time to be checking.
+ CGM.ErrorUnsupported(&S, "invalid goto to VLA scope that has finished");
+}
+
void CodeGenFunction::EmitBranch(llvm::BasicBlock *Target) {
// Emit a branch from the current block to the target one if this
// was a real block. If this was just a fall-through block after a
@@ -205,6 +241,22 @@
void CodeGenFunction::EmitLabel(const LabelStmt &S) {
llvm::BasicBlock *NextBB = getBasicBlockForLabel(&S);
+ if (StackDepthMap.find(&S) == StackDepthMap.end()) {
+ // We need to remember the stack depth so that we can readjust the
+ // stack back to the right depth for this label if we want to
+ // transfer here from a different depth.
+ StackDepthMap[&S] = StackDepth;
+ } else {
+ if (StackDepthMap[&S] != StackDepth) {
+ // FIXME: Sema needs to ckeck for jumps that cross decls with
+ // initializations for C++, and all VLAs, not just the first in
+ // a block that does a stacksave.
+ // FIXME: We need to save a place to insert the adjustment
+ // when we do a EmitStackUpdate on a forward jump, and then
+ // backpatch the adjustment into that place.
+ CGM.ErrorUnsupported(&S, "forward goto inside scope with VLA");
+ }
+ }
EmitBlock(NextBB);
}
@@ -221,18 +273,16 @@
return;
}
- for (unsigned i = 0; i < StackSaveValues.size(); i++) {
- if (StackSaveValues[i]) {
- CGM.ErrorUnsupported(&S, "goto inside scope with VLA");
- return;
- }
- }
-
// If this code is reachable then emit a stop point (if generating
// debug info). We have to do this ourselves because we are on the
// "simple" statement path.
if (HaveInsertPoint())
EmitStopPoint(&S);
+
+ // We need to adjust the stack, if the destination was (will be) at
+ // a different depth.
+ EmitStackUpdate(*S.getLabel());
+
EmitBranch(getBasicBlockForLabel(S.getLabel()));
}
@@ -330,14 +380,13 @@
Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
// Store the blocks to use for break and continue.
- BreakContinueStack.push_back(BreakContinue(ExitBlock, LoopHeader,
- ObjCEHStack.size()));
+ BreakContinuePush(ExitBlock, LoopHeader);
// Emit the loop body.
EmitBlock(LoopBody);
EmitStmt(S.getBody());
- BreakContinueStack.pop_back();
+ BreakContinuePop();
// Cycle to the condition.
EmitBranch(LoopHeader);
@@ -364,13 +413,12 @@
llvm::BasicBlock *DoCond = createBasicBlock("do.cond");
// Store the blocks to use for break and continue.
- BreakContinueStack.push_back(BreakContinue(AfterDo, DoCond,
- ObjCEHStack.size()));
+ BreakContinuePush(AfterDo, DoCond);
// Emit the body of the loop into the block.
EmitStmt(S.getBody());
- BreakContinueStack.pop_back();
+ BreakContinuePop();
EmitBlock(DoCond);
@@ -443,13 +491,12 @@
ContinueBlock = CondBlock;
// Store the blocks to use for break and continue.
- BreakContinueStack.push_back(BreakContinue(AfterFor, ContinueBlock,
- ObjCEHStack.size()));
+ BreakContinuePush(AfterFor, ContinueBlock);
// If the condition is true, execute the body of the for stmt.
EmitStmt(S.getBody());
- BreakContinueStack.pop_back();
+ BreakContinuePop();
// If there is an increment, emit it next.
if (S.getInc()) {
@@ -678,12 +725,11 @@
llvm::BasicBlock *ContinueBlock = NULL;
if (!BreakContinueStack.empty())
ContinueBlock = BreakContinueStack.back().ContinueBlock;
- BreakContinueStack.push_back(BreakContinue(NextBlock, ContinueBlock,
- ObjCEHStack.size()));
+ BreakContinuePush(NextBlock, ContinueBlock);
// Emit switch body.
EmitStmt(S.getBody());
- BreakContinueStack.pop_back();
+ BreakContinuePop();
// Update the default block in case explicit case range tests have
// been chained on top.
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=64014&r1=64013&r2=64014&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Sat Feb 7 06:52:26 2009
@@ -24,7 +24,7 @@
CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
: CGM(cgm), Target(CGM.getContext().Target), SwitchInsn(NULL),
- CaseRangeBlock(NULL) {
+ CaseRangeBlock(NULL), StackDepth(0) {
LLVMIntTy = ConvertType(getContext().IntTy);
LLVMPointerWidth = Target.getPointerWidth(0);
}
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=64014&r1=64013&r2=64014&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Sat Feb 7 06:52:26 2009
@@ -144,21 +144,36 @@
/// until all AddrLabelExprs have been seen.
std::vector<llvm::SwitchInst*> IndirectSwitches;
- /// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C
- /// decls.
+ /// LocalDeclMap - This keeps track of the LLVM allocas or globals for local
+ /// C decls.
llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
/// LabelMap - This keeps track of the LLVM basic block for each C label.
llvm::DenseMap<const LabelStmt*, llvm::BasicBlock*> LabelMap;
+ /// BreakContinuePush - Note a new break and continue level.
+ void BreakContinuePush(llvm::BasicBlock *bb, llvm::BasicBlock *cb) {
+ BreakContinueStack.push_back(BreakContinue(bb, cb, StackDepth,
+ ObjCEHStack.size()));
+ }
+
+ /// BreakContinuePop - Note end of previous break and continue level.
+ void BreakContinuePop() {
+ BreakContinueStack.pop_back();
+ }
+
// BreakContinueStack - This keeps track of where break and continue
- // statements should jump to, as well as the size of the eh stack.
+ // statements should jump to, as well as the depth of the stack and the size
+ // of the eh stack.
struct BreakContinue {
- BreakContinue(llvm::BasicBlock *bb, llvm::BasicBlock *cb, size_t ehss)
- : BreakBlock(bb), ContinueBlock(cb), EHStackSize(ehss) {}
+ BreakContinue(llvm::BasicBlock *bb, llvm::BasicBlock *cb,
+ llvm::Value *sd, size_t ehss)
+ : BreakBlock(bb), ContinueBlock(cb), SaveStackDepth(sd),
+ EHStackSize(ehss) {}
llvm::BasicBlock *BreakBlock;
llvm::BasicBlock *ContinueBlock;
+ llvm::Value *SaveStackDepth;
size_t EHStackSize;
};
llvm::SmallVector<BreakContinue, 8> BreakContinueStack;
@@ -176,11 +191,23 @@
// we enter/leave scopes.
llvm::DenseMap<const VariableArrayType*, llvm::Value*> VLASizeMap;
+ /// StackDepth - This keeps track of the stack depth. It is used to
+ /// notice when control flow results in a change in stack depth and
+ /// to arrange for the appropriate stack depth to be restored.
+ llvm::Value *StackDepth;
+
/// StackSaveValues - A stack(!) of stack save values. When a new scope is
/// entered, a null is pushed on this stack. If a VLA is emitted, then
/// the return value of llvm.stacksave() is stored at the top of this stack.
llvm::SmallVector<llvm::Value*, 8> StackSaveValues;
+ llvm::DenseMap<const LabelStmt*, llvm::Value *> StackDepthMap;
+
+ /// EmitStackUpdate - Routine to adjust the stack to the depth the
+ /// stack should be at by the time we transfer control flow to the
+ /// label.
+ void EmitStackUpdate(const LabelStmt &S);
+
public:
CodeGenFunction(CodeGenModule &cgm);
More information about the cfe-commits
mailing list