]> granicus.if.org Git - clang/commitdiff
Wire up break and continue processing to the new stack depth adjuster.
authorMike Stump <mrs@apple.com>
Sun, 8 Feb 2009 09:22:19 +0000 (09:22 +0000)
committerMike Stump <mrs@apple.com>
Sun, 8 Feb 2009 09:22:19 +0000 (09:22 +0000)
If people could beat on it and let me know if there are any new
semantics required by newer language standards or DRs or any little
details I goofed on, I'd be happy to fix any issues found.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64079 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGStmt.cpp
lib/CodeGen/CodeGenFunction.h

index 19977ec380e52a26ae1db4ed45f8907c10bc9e82..5072d63593f3109181251ca08df4c6ca2ef00130 100644 (file)
@@ -198,20 +198,7 @@ void CodeGenFunction::EmitBlock(llvm::BasicBlock *BB, bool IsFinished) {
   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)
@@ -227,10 +214,25 @@ void CodeGenFunction::EmitStackUpdate(const LabelStmt &S) {
         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) {
@@ -250,24 +252,30 @@ 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);
 }
 
@@ -292,7 +300,11 @@ void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
 
   // 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()));
 }
@@ -595,18 +607,17 @@ void CodeGenFunction::EmitBreakStmt(const BreakStmt &S) {
     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);
 }
@@ -620,18 +631,17 @@ void CodeGenFunction::EmitContinueStmt(const ContinueStmt &S) {
     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);
 }
index 836a36f95298038e35b97b8dedbae96a56b78d37..320e26b82d7419d60e27ef3c944c4ef1ecd8f640 100644 (file)
@@ -264,12 +264,28 @@ private:
   /// 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.