[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 09:19:19 PST 2010
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.
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();
More information about the llvm-commits
mailing list