[llvm-commits] [llvm-gcc-4.2] r105493 - 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 4 15:36:06 PDT 2010
Author: stuart
Date: Fri Jun 4 17:36:06 2010
New Revision: 105493
URL: http://llvm.org/viewvc/llvm-project?rev=105493&view=rev
Log:
Support for nested functions/classes in debug output. 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=105493&r1=105492&r2=105493&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Fri Jun 4 17:36:06 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,7 @@
// Convert the AST to raw/ugly LLVM code.
Function *Fn;
{
- TreeToLLVM Emitter(fndecl);
+ TreeToLLVM *Emitter = new TreeToLLVM(fndecl);
enum symbol_visibility vis = DECL_VISIBILITY (fndecl);
if (vis != VISIBILITY_DEFAULT)
@@ -1026,7 +1028,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=105493&r1=105492&r2=105493&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Fri Jun 4 17:36:06 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=105493&r1=105492&r2=105493&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp Fri Jun 4 17:36:06 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.
@@ -406,20 +437,36 @@
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);
+
+ switch (TREE_CODE(Node)) {
+ default:
+ assert("non-BLOCK, non-FUNCTION_DECL scope!");
+ case FUNCTION_DECL:
+ return CreateSubprogramFromFnDecl(Node);
+ case BLOCK:
+ // Recursively establish ancestor scopes.
+ DIDescriptor context = findRegion(BLOCK_SUPERCONTEXT(Node));
+ DILexicalBlock lexical_block =
+ DebugFactory.CreateLexicalBlock(context, CurLineNo);
+ RegionMap[Node] = WeakVH(lexical_block);
+ return DIDescriptor(lexical_block);
+ }
}
// Otherwise main compile unit covers everything.
@@ -651,7 +698,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 +785,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=105493&r1=105492&r2=105493&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-debug.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-debug.h Fri Jun 4 17:36:06 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=105493&r1=105492&r2=105493&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Fri Jun 4 17:36:06 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