[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

Stuart Hastings stuart at apple.com
Mon Jan 18 13:33:38 PST 2010


On Jan 18, 2010, at 1:02 PM, Chris Lattner wrote:

>
> 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?

I will look into this.  I can't make it entirely free, as I have to  
insure that locals get declared in the same order, with and without  
debug.

>  Also, in .cpp files, please use "tree exp" instead of "tree_node  
> *exp".

Oops.

> Also, seen_blocks should probably be named "SeenBlocks" and be a  
> SmallPtrSet.

O.K., I'll fix those.

Thanks,

stuart

>
> -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