[llvm-commits] [llvm-gcc-4.2] r93727 - in /llvm-gcc-4.2/trunk/gcc: llvm-convert.cpp llvm-debug.cpp llvm-debug.h llvm-internal.h

Chris Lattner clattner at apple.com
Mon Jan 18 13:02:12 PST 2010


On Jan 18, 2010, at 9:19 AM, Stuart Hastings wrote:

> Author: stuart
> Date: Mon Jan 18 11:19:18 2010
> New Revision: 93727
>
> URL: http://llvm.org/viewvc/llvm-project?rev=93727&view=rev
> Log:
> Radar 7387470
> Support for lexical blocks in DWARF.
>
> Declare local variables inside their lexical blocks.  This required a
> change to the order of declaration of local variables, exposing many
> latent bugs in the GCC front-end (hopefully all previously addressed).
> Note that variables must be emitted in the same order with and without
> debug output for consistency.

hi Stuart,

This does a lot of work even when debug info is not turned on.  Is it  
possible to avoid doing anything when it isn't enabled?  Also, in .cpp  
files, please use "tree exp" instead of "tree_node *exp".  Also,  
seen_blocks should probably be named "SeenBlocks" and be a SmallPtrSet.

-Chris

>
> Modified:
>    llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
>    llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp
>    llvm-gcc-4.2/trunk/gcc/llvm-debug.h
>    llvm-gcc-4.2/trunk/gcc/llvm-internal.h
>
> Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=93727&r1=93726&r2=93727&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
> +++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Mon Jan 18 11:19:18 2010
> @@ -414,6 +414,32 @@
>   return (Val = false);
> }
>
> +// Walk the GCC BLOCK() tree.  Set BLOCK_NUMBER() to the depth of  
> each
> +// block; this is necessary for lexical block debug info.  Visit all
> +// the BLOCK_VARS(), and add them to the set s.  Since the
> +// unexpanded_var_list seems to be a superset of all the scoped
> +// variables in every lexical BLOCK(), this facilitates allocating  
> the
> +// scoped variables in their blocks, and the rest at the outermost
> +// scope of the function.
> +void TreeToLLVM::setLexicalBlockDepths(tree_node *t, treeset &s,  
> unsigned level) {
> +  tree bstep, step;
> +  switch (TREE_CODE(t)) {
> +  default:
> +    abort();
> +  case BLOCK:
> +    for (bstep = t; bstep; bstep = TREE_CHAIN(bstep)) {
> +      BLOCK_NUMBER(bstep) = level;
> +      for (step = BLOCK_VARS(t); step; step = TREE_CHAIN(step))
> +	s.insert(step);
> +    }
> +    for (bstep = BLOCK_SUBBLOCKS(t); bstep; bstep =  
> TREE_CHAIN(bstep))
> +      setLexicalBlockDepths(bstep, s, level+1);
> +    return;
> +  case FUNCTION_DECL:
> +    return setLexicalBlockDepths(DECL_INITIAL(t), s, level);
> +  }
> +}
> +
> void TreeToLLVM::StartFunctionBody() {
>   const char *Name = "";
>   // Get the name of the function.
> @@ -565,6 +591,11 @@
>   // Create a new basic block for the function.
>   Builder.SetInsertPoint(BasicBlock::Create(Context, "entry", Fn));
>
> +  treeset block_declared_vars;
> +  // Set the BLOCK_NUMBER()s to the depth of each lexical block.
> +  setLexicalBlockDepths(FnDecl, block_declared_vars, 1);
> +  seen_blocks.clear();
> +
>   if (TheDebugInfo)
>     TheDebugInfo->EmitFunctionStart(FnDecl, Fn,  
> Builder.GetInsertBlock());
>
> @@ -657,10 +688,14 @@
>   // As it turns out, not all temporaries are associated with  
> blocks.  For those
>   // that aren't, emit them now.
>   for (tree t = cfun->unexpanded_var_list; t; t = TREE_CHAIN(t)) {
> -    if (!DECL_LLVM_SET_P(TREE_VALUE(t)))
> +    if (!DECL_LLVM_SET_P(TREE_VALUE(t)) &&
> +	block_declared_vars.find(TREE_VALUE(t)) ==  
> block_declared_vars.end())
>       EmitAutomaticVariableDecl(TREE_VALUE(t));
>   }
>
> +  // Push the outermost lexical block onto the RegionStack.
> +  switchLexicalBlock(DECL_INITIAL(FnDecl));
> +
>   // Create a new block for the return node, but don't insert it yet.
>   ReturnBB = BasicBlock::Create(Context, "return");
> }
> @@ -786,6 +821,96 @@
>   return FinishFunctionBody();
> }
>
> +// Given a GCC lexical context (BLOCK or FUNCTION_DECL), make it the
> +// new current BLOCK/context/scope.  Emit any local variables found
> +// in the new context.  Note that the variable emission order must be
> +// consistent with and without debug info; otherwise, the register
> +// allocation would change with -g, and users dislike that.
> +void TreeToLLVM::switchLexicalBlock(tree_node *exp) {
> +  if (exp == NULL_TREE || TREE_CODE(exp) == FUNCTION_DECL) {
> +    // assert(RegionStack empty);
> +    if (TheDebugInfo)
> +      TheDebugInfo->setCurrentLexicalBlock(exp);
> +    return;
> +  }
> +
> +  // Only EXPR_P nodes have a TREE_BLOCK() field.
> +  if (!EXPR_P(exp) && (TREE_CODE(exp) != BLOCK))
> +    return;
> +
> +  tree new_block = EXPR_P(exp) ? TREE_BLOCK(exp) : exp;
> +
> +  if (!new_block)
> +    return;
> +
> +  // Have we seen this BLOCK before?
> +  bool previously_visited = (seen_blocks.find(new_block) !=  
> seen_blocks.end());
> +
> +  // If new_block is nested inside another block, and we haven't
> +  // processed either block, insure the outer block(s) get processed
> +  // first.
> +  if (!previously_visited)
> +    switchLexicalBlock(BLOCK_SUPERCONTEXT(new_block));
> +
> +  if (TheDebugInfo) {
> +    tree current_block = TheDebugInfo->getCurrentLexicalBlock();
> +    if (new_block && current_block && new_block != current_block) {
> +      tree new_climber = new_block, current_climber = current_block;
> +      unsigned new_climber_depth, current_climber_depth;
> +      // Climb the GCC BLOCK hierarchy, looking for a common parent
> +      // BLOCK or FUNCTION_DECL.  Assume BLOCK_NUMBER() fields set to
> +      // depth by setLexicalBlockDepths().  If the climber depths are
> +      // equal, but the climbers differ, they are siblings: both
> +      // climbers rise to the next level.
> +      while (new_climber != current_climber) {
> +	current_climber_depth = DECL_P(current_climber) ? 0 :  
> BLOCK_NUMBER(current_climber);
> +	new_climber_depth = DECL_P(new_climber) ? 0 :  
> BLOCK_NUMBER(new_climber);
> +	if (new_climber_depth <= current_climber_depth)
> +	  current_climber = BLOCK_SUPERCONTEXT(current_climber);
> +	if (new_climber_depth >= current_climber_depth)
> +	  new_climber = BLOCK_SUPERCONTEXT(new_climber);
> +      }
> +      assert(new_climber == current_climber && "missed common  
> TREE_BLOCK parent");
> +      // Pop and push lexical blocks to arrive at the new context.
> +      TheDebugInfo->change_regions(new_block, new_climber);
> +    }
> +  }
> +
> +  // If we've seen this lexical BLOCK before, we're done.
> +  if (previously_visited)
> +    return;
> +
> +  // O.K., this lexical BLOCK is new to us; remember it for next  
> time.
> +  seen_blocks.insert(new_block);
> +
> +  // Finally, allocate any BLOCK_VARS we find.
> +  tree step;
> +  for (step = BLOCK_VARS(new_block); step; step = TREE_CHAIN(step))
> +    switch (TREE_CODE_CLASS(TREE_CODE(step))) {
> +    default:
> +      assert(0 && "non-var, non-type node hanging from a GCC  
> BLOCK?");
> +      break;
> +    case tcc_type:
> +      // GCC has recorded a lexical block scope for this type, but
> +      // ConvertType() doesn't currently handle scopes for types.
> +      break;
> +    case tcc_declaration:
> +      if (!DECL_LLVM_SET_P(step))
> +	EmitAutomaticVariableDecl(step);
> +      break;
> +    }
> +
> +  // Kludge! The Objective-C++ front-end doesn't always point to the
> +  // right BLOCK. :-( Test case g++.apple/block-assigncglobal.C has a
> +  // block (closure) where the first statement (a MODIFY_EXPR) points
> +  // to a lexical BLOCK that has no BLOCK_VARS, but it has a subblock
> +  // with the decl for the target of the MODIFY.  Ergo, if we
> +  // encounter a BLOCK that allocates no variables, check for a
> +  // subblock.  A better fix would be in the front-end.
> +  if (!BLOCK_VARS(new_block) && BLOCK_SUBBLOCKS(new_block))
> +    switchLexicalBlock(BLOCK_SUBBLOCKS(new_block));
> +}
> +
> Value *TreeToLLVM::Emit(tree exp, const MemRef *DestLoc) {
>   assert((isAggregateTreeType(TREE_TYPE(exp)) == (DestLoc != 0) ||
>           TREE_CODE(exp) == MODIFY_EXPR || TREE_CODE(exp) ==  
> INIT_EXPR) &&
> @@ -793,6 +918,10 @@
>
>   Value *Result = 0;
>
> +  // If we've just changed lexical blocks, emit any local variables
> +  // declared in the new block.
> +  TreeToLLVM::switchLexicalBlock(exp);
> +
>   if (TheDebugInfo) {
>     if (EXPR_HAS_LOCATION(exp)) {
>       // Set new location on the way up the tree.
>
> Modified: llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp?rev=93727&r1=93726&r2=93727&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp (original)
> +++ llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp Mon Jan 18 11:19:18 2010
> @@ -228,10 +228,46 @@
>     return false;
> }
>
> +// Starting at the 'desired' BLOCK, recursively walk back to the
> +// 'grand' context, and return pushing regions to make 'desired' the
> +// current context.  Assumes 'grand' is a
> +// parent/grandparent/great-grandparent of 'desired'.  'desired'
> +// should be a GCC lexical BLOCK, and 'grand' may be a BLOCK or a
> +// FUNCTION_DECL.
> +void DebugInfo::push_regions(tree desired, tree grand) {
> +  assert (grand && "'grand' BLOCK is NULL?");
> +  assert (desired &&
> +          "'desired' BLOCK is NULL; is grand BLOCK really a parent  
> of desired BLOCK?");
> +  assert ((TREE_CODE(desired) == BLOCK || TREE_CODE(desired) ==  
> FUNCTION_DECL) &&
> +          "expected 'desired' to be a GCC BLOCK or FUNCTION_DECL");
> +  assert ((TREE_CODE(grand) == BLOCK || TREE_CODE(grand) ==  
> FUNCTION_DECL) &&
> +          "expected 'grand' to be a GCC BLOCK or FUNCTION_DECL");
> +  if (grand != desired)
> +    push_regions(BLOCK_SUPERCONTEXT(desired), grand);
> +  llvm::DIDescriptor D = findRegion(desired);
> +  RegionStack.push_back(D.getNode());
> +}
> +
> +// Pop the current region/lexical-block back to 'grand', then push
> +// regions to arrive at 'desired'.  This was inspired (cribbed from)
> +// by GCC's cfglayout.c:change_scope().
> +void DebugInfo::change_regions(tree desired, tree grand) {
> +  tree current_lexical_block = getCurrentLexicalBlock();
> +  while (current_lexical_block != grand) {
> +    assert(BLOCK_SUPERCONTEXT(getCurrentLexicalBlock()) &&
> +           "lost BLOCK context!");
> +    current_lexical_block =  
> BLOCK_SUPERCONTEXT(current_lexical_block);
> +    RegionStack.pop_back();
> +  }
> +  DebugInfo::push_regions(desired, grand);
> +  setCurrentLexicalBlock(desired);
> +}
> +
> /// EmitFunctionStart - Constructs the debug code for entering a  
> function -
> /// "llvm.dbg.func.start."
> void DebugInfo::EmitFunctionStart(tree FnDecl, Function *Fn,
>                                   BasicBlock *CurBB) {
> +  setCurrentLexicalBlock(FnDecl);
>
>   DIType FNType = getOrCreateType(TREE_TYPE(FnDecl));
>
> @@ -329,6 +365,13 @@
>       return DIDescriptor(NS.getNode());
>     }
>     return findRegion (DECL_CONTEXT (Node));
> +  } else if (TREE_CODE(Node) == BLOCK) {
> +    // TREE_BLOCK is GCC's lexical block.
> +    // Recursively create all necessary contexts:
> +    DIDescriptor context = findRegion(BLOCK_SUPERCONTEXT(Node));
> +    DILexicalBlock lexical_block =  
> DebugFactory.CreateLexicalBlock(context);
> +    RegionMap[Node] = WeakVH(lexical_block.getNode());
> +    return DIDescriptor(lexical_block);
>   }
>
>   // Otherwise main compile unit covers everything.
> @@ -347,6 +390,7 @@
>     PrevLineNo = 0;
>     PrevFullPath = NULL;
>   }
> +  setCurrentLexicalBlock(NULL_TREE);
> }
>
> /// EmitDeclare - Constructs the debug code for allocation of a new  
> variable.
>
> Modified: llvm-gcc-4.2/trunk/gcc/llvm-debug.h
> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-debug.h?rev=93727&r1=93726&r2=93727&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- llvm-gcc-4.2/trunk/gcc/llvm-debug.h (original)
> +++ llvm-gcc-4.2/trunk/gcc/llvm-debug.h Mon Jan 18 11:19:18 2010
> @@ -61,6 +61,7 @@
>   const char *PrevFullPath;             // Previous location file  
> encountered.
>   int PrevLineNo;                       // Previous location line#  
> encountered.
>   BasicBlock *PrevBB;                   // Last basic block  
> encountered.
> +  tree_node *CurrentGCCLexicalBlock;	// Current GCC lexical block  
> (or enclosing FUNCTION_DECL).
>   std::map<std::string, WeakVH > CUCache;
>   std::map<tree_node *, WeakVH > TypeCache;
>                                         // Cache of previously  
> constructed
> @@ -75,6 +76,9 @@
>                                         // Stack to track  
> declarative scopes.
>
>   std::map<tree_node *, WeakVH> RegionMap;
> +
> +  void push_regions(tree_node *desired, tree_node *grand);
> +
> public:
>   DebugInfo(Module *m);
>
> @@ -87,6 +91,11 @@
>   void setLocationFile(const char *FullPath) { CurFullPath =  
> FullPath; }
>   void setLocationLine(int LineNo)           { CurLineNo = LineNo; }
>
> +  tree_node *getCurrentLexicalBlock() { return  
> CurrentGCCLexicalBlock; }
> +  void setCurrentLexicalBlock(tree_node *lb)  
> { CurrentGCCLexicalBlock = lb; }
> +
> +  void change_regions(tree_node *desired, tree_node *grand);
> +
>   /// EmitFunctionStart - Constructs the debug code for entering a  
> function -
>   /// "llvm.dbg.func.start."
>   void EmitFunctionStart(tree_node *FnDecl, Function *Fn, BasicBlock  
> *CurBB);
>
> Modified: llvm-gcc-4.2/trunk/gcc/llvm-internal.h
> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-internal.h?rev=93727&r1=93726&r2=93727&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original)
> +++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Mon Jan 18 11:19:18 2010
> @@ -68,6 +68,7 @@
> using namespace llvm;
>
> typedef IRBuilder<true, TargetFolder> LLVMBuilder;
> +typedef std::set<union tree_node *> treeset;
>
> /// TheModule - This is the current global module that we are  
> compiling into.
> ///
> @@ -278,6 +279,7 @@
>   BasicBlock *ReturnBB;
>   BasicBlock *UnwindBB;
>   unsigned ReturnOffset;
> +  std::set<tree_node*> seen_blocks;
>
>   // State that changes as the function is emitted.
>
> @@ -380,8 +382,26 @@
>   /// GCC type specified by GCCType to know which elements to copy.
>   void EmitAggregateCopy(MemRef DestLoc, MemRef SrcLoc, tree_node  
> *GCCType);
>
> +  // 'desired' and 'grand' are GCC BLOCK nodes, representing lexical
> +  // blocks.  Assumes we're in the 'grand' context; push contexts
> +  // until we reach the 'desired' context.
> +  void push_regions(tree_node *desired, tree_node *grand);
> +
> +  // Given a GCC lexical context (BLOCK or FUNCTION_DECL), make it  
> the
> +  // new current BLOCK/context/scope.  Emit any local variables found
> +  // in the new context.  Note that the variable emission order  
> must be
> +  // consistent with and without debug info; otherwise, the register
> +  // allocation would change with -g, and users dislike that.
> +  void switchLexicalBlock(tree_node *exp);
> +
> private: // Helper functions.
>
> +  // Walk over the lexical BLOCK() tree of the given FUNCTION_DECL;
> +  // set the BLOCK_NUMBER() fields to the depth of each block, and
> +  // add every var or type encountered in the BLOCK_VARS() lists to
> +  // the given set.
> +  void setLexicalBlockDepths(tree_node *t, treeset &s, unsigned  
> level);
> +
>   /// StartFunctionBody - Start the emission of 'fndecl', outputing  
> all
>   /// declarations for parameters and setting things up.
>   void StartFunctionBody();
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list