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

Stuart Hastings stuart at apple.com
Fri Jun 11 13:08:48 PDT 2010


Author: stuart
Date: Fri Jun 11 15:08:47 2010
New Revision: 105829

URL: http://llvm.org/viewvc/llvm-project?rev=105829&view=rev
Log:
Support for nested functions/classes in debug output.  (Again.)  Radar 7424645.

Modified:
    llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp
    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-backend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp?rev=105829&r1=105828&r2=105829&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Fri Jun 11 15:08:47 2010
@@ -526,6 +526,8 @@
 
   if (debug_info_level > DINFO_LEVEL_NONE)
     TheDebugInfo = new DebugInfo(TheModule);
+  else
+    TheDebugInfo = 0;
 }
 
 /// performLateBackendInitialization - Set backend options that may only be
@@ -1018,7 +1020,8 @@
   // Convert the AST to raw/ugly LLVM code.
   Function *Fn;
   {
-    TreeToLLVM Emitter(fndecl);
+    TreeToLLVM *Emitter = new TreeToLLVM(fndecl);
+    // FIXME: should we store TheTreeToLLVM right here (current in constructor)?
     enum symbol_visibility vis = DECL_VISIBILITY (fndecl);
 
     if (vis != VISIBILITY_DEFAULT)
@@ -1026,7 +1029,8 @@
       // visibility that's not supported by the target.
       targetm.asm_out.visibility(fndecl, vis);
 
-    Fn = Emitter.EmitFunction();
+    Fn = TheTreeToLLVM->EmitFunction();
+    Emitter->~TreeToLLVM();
   }
 
 #if 0

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=105829&r1=105828&r2=105829&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Fri Jun 11 15:08:47 2010
@@ -148,7 +148,7 @@
 //===----------------------------------------------------------------------===//
 
 /// TheTreeToLLVM - Keep track of the current function being compiled.
-static TreeToLLVM *TheTreeToLLVM = 0;
+TreeToLLVM *TheTreeToLLVM = 0;
 
 const TargetData &getTargetData() {
   return *TheTarget->getTargetData();
@@ -157,7 +157,7 @@
 /// EmitDebugInfo - Return true if debug info is to be emitted for current 
 /// function.
 bool TreeToLLVM::EmitDebugInfo() {
-  if (TheDebugInfo && !DECL_IGNORED_P(getFUNCTION_DECL()))
+  if (TheDebugInfo && getFUNCTION_DECL() && !DECL_IGNORED_P(getFUNCTION_DECL()))
     return true;
   return false;
 }
@@ -616,7 +616,7 @@
   SeenBlocks.clear();
 
   if (EmitDebugInfo())
-    TheDebugInfo->EmitFunctionStart(FnDecl, Fn, Builder.GetInsertBlock());
+    TheDebugInfo->EmitFunctionStart(FnDecl);
 
   // Loop over all of the arguments to the function, setting Argument names and
   // creating argument alloca's for the PARM_DECLs in case their address is
@@ -631,7 +631,7 @@
   ABIConverter.HandleReturnType(TREE_TYPE(TREE_TYPE(FnDecl)), FnDecl,
                                 DECL_BUILT_IN(FnDecl));
   // Remember this for use by FinishFunctionBody.
-  TheTreeToLLVM->ReturnOffset = Client.Offset;
+  ReturnOffset = Client.Offset;
 
   // Prepend the static chain (if any) to the list of arguments.
   tree Args = static_chain ? static_chain : DECL_ARGUMENTS(FnDecl);

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=105829&r1=105828&r2=105829&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp Fri Jun 11 15:08:47 2010
@@ -277,7 +277,7 @@
 // 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();
+  tree current_lexical_block = getCurrentLexicalBlock(), t;
   // FIXME: change_regions is currently never called with desired ==
   // grand, but it should be fixed so nothing weird happens if they're
   // equal.
@@ -288,28 +288,34 @@
     RegionStack.pop_back();
   }
   DebugInfo::push_regions(desired, grand);
-  setCurrentLexicalBlock(desired);
+  // There's no point in declaring an empty (declares no variables)
+  // lexical BLOCK as the current lexical BLOCK.  Locate nearest
+  // non-empty ancestor BLOCK and declare that.
+  for (t = desired; TREE_CODE(t) == BLOCK; t = BLOCK_SUPERCONTEXT(t))
+    if (BLOCK_VARS(t))
+      break;
+  setCurrentLexicalBlock(t);
 }
 
-/// EmitFunctionStart - Constructs the debug code for entering a function.
-void DebugInfo::EmitFunctionStart(tree FnDecl, Function *Fn,
-                                  BasicBlock *CurBB) {
-  setCurrentLexicalBlock(FnDecl);
-
+/// CreateSubprogramFromFnDecl - Constructs the debug code for
+/// entering a function - "llvm.dbg.func.start."
+DISubprogram DebugInfo::CreateSubprogramFromFnDecl(tree FnDecl) {
+  DISubprogram SPDecl;
+  bool SPDeclIsSet = false;
+  // True if we're currently generating LLVM for this function.
+  bool definition = llvm_set_decl_p(FnDecl);
   DIType FNType = getOrCreateType(TREE_TYPE(FnDecl));
 
   std::map<tree_node *, WeakVH >::iterator I = SPCache.find(FnDecl);
   if (I != SPCache.end()) {
-    DISubprogram SPDecl(cast<MDNode>(I->second));
-    DISubprogram SP = 
-      DebugFactory.CreateSubprogramDefinition(SPDecl);
-    SPDecl->replaceAllUsesWith(SP);
-
-    // Push function on region stack.
-    RegionStack.push_back(WeakVH(SP));
-    RegionMap[FnDecl] = WeakVH(SP);
-    return;
-  } 
+    SPDecl = DISubprogram(cast<MDNode>(I->second));
+    SPDeclIsSet = true;
+    // If we've already created the defining instance, OR this
+    // invocation won't create the defining instance, return what we
+    // already have.
+    if (SPDecl.isDefinition() || !definition)
+      return SPDecl;
+  }
 
   bool ArtificialFnWithAbstractOrigin = false;
   // If this artificial function has abstract origin then put this function
@@ -323,26 +329,34 @@
     getOrCreateFile(main_input_filename) :
     findRegion (DECL_CONTEXT(FnDecl));
 
+  // Declare block_invoke functions at file scope for GDB.
+  if (BLOCK_SYNTHESIZED_FUNC(FnDecl))
+    SPContext = findRegion(NULL_TREE);
+
   // Creating context may have triggered creation of this SP descriptor. So
   // check the cache again.
-  I = SPCache.find(FnDecl);
-  if (I != SPCache.end()) {
-    DISubprogram SPDecl(cast<MDNode>(I->second));
-    DISubprogram SP = 
-      DebugFactory.CreateSubprogramDefinition(SPDecl);
-    SPDecl->replaceAllUsesWith(SP);
-
-    // Push function on region stack.
-    RegionStack.push_back(WeakVH(SP));
-    RegionMap[FnDecl] = WeakVH(SP);
-    return;
-  } 
+  if (!SPDeclIsSet) {
+    I = SPCache.find(FnDecl);
+    if (I != SPCache.end()) {
+      SPDecl = DISubprogram(cast<MDNode>(I->second));
+      DISubprogram SP = 
+        DebugFactory.CreateSubprogramDefinition(SPDecl);
+      SPDecl->replaceAllUsesWith(SP);
 
+      // Push function on region stack.
+      RegionStack.push_back(WeakVH(SP));
+      RegionMap[FnDecl] = WeakVH(SP);
+      return SP;
+    }
+  }
   // Gather location information.
   expanded_location Loc = GetNodeLocation(FnDecl, false);
-  StringRef LinkageName = getLinkageName(FnDecl);
+  // If the name isn't public, omit the linkage name.  Adding a
+  // linkage name to a class method can confuse GDB.
+  StringRef LinkageName = TREE_PUBLIC(FnDecl) ?
+    getLinkageName(FnDecl) : StringRef();
 
-  unsigned lineno = CurLineNo;
+  unsigned lineno = LOCATION_LINE(Loc);
   if (isCopyOrDestroyHelper(FnDecl))
     lineno = 0;
 
@@ -357,23 +371,40 @@
   }
 
   StringRef FnName = getFunctionName(FnDecl);
-
+  // If the Function * hasn't been created yet, use a bogus value for
+  // the debug internal linkage bit.
+  bool hasInternalLinkage = true;
+  Function *Fn = 0;
+  if (GET_DECL_LLVM_INDEX(FnDecl)) {
+    Fn = cast<Function>DECL_LLVM(FnDecl);
+    if (Fn)
+      hasInternalLinkage = Fn->hasInternalLinkage();
+  }
   DISubprogram SP = 
     DebugFactory.CreateSubprogram(SPContext,
                                   FnName, FnName,
                                   LinkageName,
                                   getOrCreateFile(Loc.file), lineno,
                                   FNType,
-                                  Fn->hasInternalLinkage(),
-                                  true /*definition*/,
+                                  hasInternalLinkage,
+                                  definition,
                                   Virtuality, VIndex, ContainingType,
-                                  DECL_ARTIFICIAL (FnDecl), optimize);
+                                  DECL_ARTIFICIAL (FnDecl), optimize,
+                                  Fn);
 
   SPCache[FnDecl] = WeakVH(SP);
+  RegionMap[FnDecl] = WeakVH(SP);
+  if (SPDeclIsSet && SPDecl != SP)
+    SPDecl->replaceAllUsesWith(SP);
+  return SP;
+}
 
+/// EmitFunctionStart - Constructs the debug code for entering a function.
+void DebugInfo::EmitFunctionStart(tree FnDecl) {
+  setCurrentLexicalBlock(FnDecl);
+  DISubprogram SP = CreateSubprogramFromFnDecl(FnDecl);
   // Push function on region stack.
   RegionStack.push_back(WeakVH(SP));
-  RegionMap[FnDecl] = WeakVH(SP);
 }
 
 /// getOrCreateNameSpace - Get name space descriptor for the tree node.
@@ -392,6 +423,58 @@
   return DNS;
 }
 
+/// variablesDeclaredAtThisLevel - yield true if this block, or any
+/// sibling thereof, declares any variables or types.  Expectes a
+/// BLOCK or FUNCTION_DECL tree.
+// GDB Kludge
+static bool variablesDeclaredAtThisLevel(tree blk) {
+  if (TREE_CODE(blk) == FUNCTION_DECL)
+    return true;
+  assert(TREE_CODE(blk) == BLOCK && "expected FUNCTION_DECL or BLOCK tree");
+  tree supercontext = BLOCK_SUPERCONTEXT(blk);
+  if (!supercontext)	// External scope.  Pretend it's the same as module scope.
+    return false;
+  tree step = TREE_CODE(supercontext) == BLOCK ?
+    BLOCK_SUBBLOCKS(supercontext) : DECL_INITIAL(supercontext);
+  for ( ; step && TREE_CODE(step) == BLOCK; step = TREE_CHAIN(step))
+    if (BLOCK_VARS(step))
+      return true;
+  return false;
+}
+
+/// supercontextWithDecls - walk up the BLOCKS tree, return an
+/// ancestor BLOCK that has vars, or sibling BLOCKs that do.  May
+/// return the FUNCTION_DECL.
+// GDB Kludge
+static tree supercontextWithDecls(tree blk) {
+  assert(TREE_CODE(blk) == BLOCK && "expected BLOCK");
+  tree step = BLOCK_SUPERCONTEXT(blk);
+  if (!step)    // No parent BLOCKs to search.
+    return blk;
+  while (step && TREE_CODE(step) == BLOCK && BLOCK_SUPERCONTEXT(step) &&
+         !variablesDeclaredAtThisLevel(step))
+    step = BLOCK_SUPERCONTEXT(step);
+  return step;
+}
+
+/// nonemptySibling - true if the given BLOCK has a sibling that is
+/// not empty (declares types and/or vars).
+// GDB Kludge
+static bool nonemptySibling(tree blk) {
+  if (TREE_CODE(blk) == FUNCTION_DECL)
+    return true;
+  assert(TREE_CODE(blk) == BLOCK && "expected FUNCTION_DECL or BLOCK tree");
+  tree supercontext = BLOCK_SUPERCONTEXT(blk);
+  if (!supercontext)	// External scope.  Pretend it's the same as module scope.
+    return false;
+  tree step = TREE_CODE(supercontext) == BLOCK ?
+    BLOCK_SUBBLOCKS(supercontext) : DECL_INITIAL(supercontext);
+  for ( ; step; step = TREE_CHAIN(step))
+    if (step != blk && BLOCK_VARS(step))
+      return true;
+  return false;
+}
+
 /// findRegion - Find tree_node N's region.
 DIDescriptor DebugInfo::findRegion(tree Node) {
   if (Node == NULL_TREE)
@@ -406,20 +489,71 @@
     DIType Ty = getOrCreateType(Node);
     return DIDescriptor(Ty);
   } else if (DECL_P (Node)) {
-    if (TREE_CODE (Node) == NAMESPACE_DECL) {
+    switch (TREE_CODE(Node)) {
+    default:
+      /// What kind of DECL is this?
+      return findRegion (DECL_CONTEXT (Node));
+    case NAMESPACE_DECL: {
       DIDescriptor NSContext = findRegion(DECL_CONTEXT(Node));
       DINameSpace NS = getOrCreateNameSpace(Node, NSContext);
       return DIDescriptor(NS);
     }
-    return findRegion (DECL_CONTEXT (Node));
+    case FUNCTION_DECL: {
+      DISubprogram SP = CreateSubprogramFromFnDecl(Node);
+      return SP;
+    }
+    }
   } 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, CurLineNo);
-    RegionMap[Node] = WeakVH(lexical_block);
-    return DIDescriptor(lexical_block);
+    tree scopeToDeclare, step;
+
+#if 0
+    // GDB Kludge
+    // This code section is devoted to eliminating as many lexical
+    // blocks as possible, in order to mimic GCC debug output.  In a
+    // perfect world, the debugger would not be adversely affected by
+    // a few extra lexical scopes.  Ideally this stuff could be
+    // drastically simplified when LLDB replaces GDB.
+    if (nonemptySibling(Node)) {
+      // If any sibling BLOCK declares anything, use this scope.
+      scopeToDeclare = Node;
+    } else {
+      tree upper = supercontextWithDecls(Node);
+      if (TREE_CODE(upper) == FUNCTION_DECL) {
+        scopeToDeclare = upper;
+      } else if (TREE_CODE(upper) == BLOCK && BLOCK_VARS(upper) && BLOCK_VARS(Node) &&
+                 upper != Node) {
+        // We can't use upper because it declares something.  Find the
+        // uppermost empty BLOCK /between/ Node and upper.
+        for (step = BLOCK_SUPERCONTEXT(Node);
+             TREE_CODE(step) == BLOCK && !BLOCK_VARS(step) &&
+               BLOCK_SUPERCONTEXT(step);
+             step = BLOCK_SUPERCONTEXT(step))
+          ;
+        scopeToDeclare = step;
+      } else
+        // Either or both of upper and Node are empty (declare
+        // nothing); fuse Node's scope with upper.
+        scopeToDeclare = upper;
+    }
+#else
+    scopeToDeclare = Node;
+#endif
+        
+    switch (TREE_CODE(scopeToDeclare)) {
+    default:
+      assert("non-BLOCK, non-FUNCTION_DECL scope!");
+    case FUNCTION_DECL:
+      return CreateSubprogramFromFnDecl(scopeToDeclare);
+    case BLOCK:
+      // Recursively establish ancestor scopes.
+      DIDescriptor context = findRegion(BLOCK_SUPERCONTEXT(scopeToDeclare));
+      DILexicalBlock lexical_block = 
+        DebugFactory.CreateLexicalBlock(context, CurLineNo);
+      RegionMap[scopeToDeclare] = WeakVH(lexical_block);
+      return DIDescriptor(lexical_block);
+    }
+    // GDB Kludge end
   }
 
   // Otherwise main compile unit covers everything.
@@ -651,7 +785,7 @@
   sprintf(FwdTypeName, "fwd.type.%d", FwdTypeCount++);
   llvm::DIType FwdType = 
     DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
-                                     getOrCreateFile(main_input_filename),
+                                     findRegion(TYPE_CONTEXT(type)),
                                      FwdTypeName,
                                      getOrCreateFile(main_input_filename),
                                      0, 0, 0, 0, 0,
@@ -738,7 +872,7 @@
   
   StringRef PName = FromTy.getName();
   DIType PTy = 
-    DebugFactory.CreateDerivedType(Tag, findRegion(TYPE_CONTEXT(type)), 
+    DebugFactory.CreateDerivedType(Tag, findRegion(TYPE_CONTEXT(type)),
                                    Tag == DW_TAG_pointer_type ? 
                                    StringRef() : PName,
                                    getOrCreateFile(main_input_filename),

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=105829&r1=105828&r2=105829&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-debug.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-debug.h Fri Jun 11 15:08:47 2010
@@ -118,9 +118,13 @@
   // by GCC's cfglayout.c:change_scope().
   void change_regions(tree_node *desired, tree_node *grand);
 
-  /// EmitFunctionStart - Constructs the debug code for entering a function -
+  /// CreateSubprogramFromFnDecl - Constructs the debug code for entering a function -
   /// "llvm.dbg.func.start."
-  void EmitFunctionStart(tree_node *FnDecl, Function *Fn, BasicBlock *CurBB);
+  DISubprogram CreateSubprogramFromFnDecl(tree_node *FnDecl);
+
+  /// EmitFunctionStart - Constructs the debug code for entering a function -
+  /// "llvm.dbg.func.start", and pushes it onto the RegionStack.
+  void EmitFunctionStart(tree_node *FnDecl);
 
   /// EmitFunctionEnd - Constructs the debug code for exiting a declarative
   /// region - "llvm.dbg.region.end."

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=105829&r1=105828&r2=105829&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Fri Jun 11 15:08:47 2010
@@ -75,7 +75,7 @@
 extern llvm::Module *TheModule;
 
 /// TheDebugInfo - This object is responsible for gather all debug information.
-/// If it's value is NULL then no debug information should be gathered.
+/// If its value is NULL then no debug information should be gathered.
 extern llvm::DebugInfo *TheDebugInfo;
 
 /// TheTarget - The current target being compiled for.
@@ -281,6 +281,7 @@
   BasicBlock *ReturnBB;
   BasicBlock *UnwindBB;
   unsigned ReturnOffset;
+
   // Lexical BLOCKS that we have previously seen and processed.
   treeset SeenBlocks;
 
@@ -397,6 +398,10 @@
   // allocation would change with -g, and users dislike that.
   void switchLexicalBlock(tree_node *exp);
 
+  /// StartFunctionBody - Start the emission of 'FnDecl', outputing all
+  /// declarations for parameters and setting things up.
+  void StartFunctionBody();
+  
 private: // Helper functions.
 
   // Walk over the lexical BLOCK() tree of the given FUNCTION_DECL;
@@ -405,10 +410,6 @@
   // 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();
-  
   /// FinishFunctionBody - Once the body of the function has been emitted, this
   /// cleans up and returns the result function.
   Function *FinishFunctionBody();
@@ -608,6 +609,9 @@
   Constant *EmitLV_LABEL_DECL(tree_node *exp);
 };
 
+/// TheTreeToLLVM - Keep track of the current function being compiled.
+extern TreeToLLVM *TheTreeToLLVM;
+
 /// TreeConstantToLLVM - An instance of this class is created and used to 
 /// convert tree constant values to LLVM.  This is primarily for things like
 /// global variable initializers.





More information about the llvm-commits mailing list