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];
+bool CodeGenFunction::EmitStackUpdate(llvm::Value *V) {
// 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)
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");
+ } else return true;
+ return false;
+}
+
+bool CodeGenFunction::EmitStackUpdate(const void *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 false;
+ }
+
+ // Find applicable stack depth, if any...
+ llvm::Value *V = StackDepthMap[S];
+ return EmitStackUpdate(V);
}
void CodeGenFunction::EmitBranch(llvm::BasicBlock *Target) {
Builder.ClearInsertionPoint();
}
-void CodeGenFunction::EmitLabel(const LabelStmt &S) {
- llvm::BasicBlock *NextBB = getBasicBlockForLabel(&S);
- if (StackDepthMap.find(&S) == StackDepthMap.end()) {
+bool CodeGenFunction::StackFixupAtLabel(const void *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;
+ StackDepthMap[S] = StackDepth;
} else {
- if (StackDepthMap[&S] != StackDepth) {
+ 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");
+ return true;
}
}
+ return false;
+}
+
+void CodeGenFunction::EmitLabel(const LabelStmt &S) {
+ llvm::BasicBlock *NextBB = getBasicBlockForLabel(&S);
+ if (StackFixupAtLabel(&S))
+ CGM.ErrorUnsupported(&S, "forward goto inside scope with VLA");
EmitBlock(NextBB);
}
// We need to adjust the stack, if the destination was (will be) at
// a different depth.
- EmitStackUpdate(*S.getLabel());
+ if (EmitStackUpdate(S.getLabel()))
+ // FIXME: Move to semq and assert here, codegen isn't the right
+ // time to be checking.
+ CGM.ErrorUnsupported(S.getLabel(),
+ "invalid goto to VLA scope that has finished");
EmitBranch(getBasicBlockForLabel(S.getLabel()));
}
return;
}
- for (unsigned i = 0; i < StackSaveValues.size(); i++) {
- if (StackSaveValues[i]) {
- CGM.ErrorUnsupported(&S, "break 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.
+ if (EmitStackUpdate(BreakContinueStack.back().SaveBreakStackDepth))
+ assert (0 && "break vla botch");
+
llvm::BasicBlock *Block = BreakContinueStack.back().BreakBlock;
EmitBranch(Block);
}
return;
}
- for (unsigned i = 0; i < StackSaveValues.size(); i++) {
- if (StackSaveValues[i]) {
- CGM.ErrorUnsupported(&S, "continue 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.
+ if (EmitStackUpdate(BreakContinueStack.back().SaveContinueStackDepth))
+ assert (0 && "continue vla botch");
+
llvm::BasicBlock *Block = BreakContinueStack.back().ContinueBlock;
EmitBranch(Block);
}
/// 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;
+ llvm::DenseMap<const void*, llvm::Value *> StackDepthMap;
+
+ /// StackFixupAtLabel - Routine to adjust the stack to the depth the
+ /// stack should be at by the time we transfer control flow to the
+ /// label. This is called as we emit destinations for control flow,
+ /// such as user labels for goto statements and compiler generated
+ /// labels for break and continue processsing. We return true, if
+ /// for any reason we can't generate code for the construct yet.
+ /// See EmitStackUpdate for the paired routine to mark the branch.
+ bool StackFixupAtLabel(const void *);
/// 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);
+ /// label. This is called just before emitting branches for user
+ /// level goto processing, branhes for break or continue processing.
+ /// The llvm::value overload is used when handling break and
+ /// continue, as we know the stack depth directly. We return true,
+ /// if for any reason we can't generate code for the construct yet.
+ /// See StackFixupAtLabel for the paired routine to mark the
+ /// destinations.
+ bool EmitStackUpdate(llvm::Value *V);
+ bool EmitStackUpdate(const void *S);
struct CleanupEntry {
/// CleanupBlock - The block of code that does the actual cleanup.