[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