summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp80
1 files changed, 67 insertions, 13 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 85a63248a21..dcc3e55a52e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -568,25 +568,79 @@ DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV,
return Var;
}
-/// Determine whether a variable appears in a count: expression.
-static bool dependsOn(DbgVariable *A, DbgVariable *B) {
- auto *Array = dyn_cast<DICompositeType>(A->getType());
+/// Return all DIVariables that appear in count: expressions.
+static SmallVector<const DIVariable *, 2> dependencies(DbgVariable *Var) {
+ SmallVector<const DIVariable *, 2> Result;
+ auto *Array = dyn_cast<DICompositeType>(Var->getType());
if (!Array || Array->getTag() != dwarf::DW_TAG_array_type)
- return false;
- return llvm::any_of(Array->getElements(), [&](DINode *El) {
+ return Result;
+ for (auto *El : Array->getElements()) {
if (auto *Subrange = dyn_cast<DISubrange>(El)) {
auto Count = Subrange->getCount();
- if (auto *Var = Count.dyn_cast<DIVariable *>())
- return Var == B->getVariable();
+ if (auto *Dependency = Count.dyn_cast<DIVariable *>())
+ Result.push_back(Dependency);
}
- return false;
- });
+ }
+ return Result;
}
/// Sort local variables so that variables appearing inside of helper
/// expressions come first.
-static bool sortLocalVars(DbgVariable *A, DbgVariable *B) {
- return dependsOn(B, A);
+static SmallVector<DbgVariable *, 8>
+sortLocalVars(SmallVectorImpl<DbgVariable *> &Input) {
+ SmallVector<DbgVariable *, 8> Result;
+ SmallVector<PointerIntPair<DbgVariable *, 1>, 8> WorkList;
+ // Map back from a DIVariable to its containing DbgVariable.
+ SmallDenseMap<const DILocalVariable *, DbgVariable *> DbgVar;
+ // Set of DbgVariables in Result.
+ SmallDenseSet<DbgVariable *, 8> Visited;
+ // For cycle detection.
+ SmallDenseSet<DbgVariable *, 8> Visiting;
+
+ // Initialize the worklist and the DIVariable lookup table.
+ for (auto Var : reverse(Input)) {
+ DbgVar.insert({Var->getVariable(), Var});
+ WorkList.push_back({Var, 0});
+ }
+
+ // Perform a stable topological sort by doing a DFS.
+ while (!WorkList.empty()) {
+ auto Item = WorkList.back();
+ DbgVariable *Var = Item.getPointer();
+ bool visitedAllDependencies = Item.getInt();
+ WorkList.pop_back();
+
+ // Dependency is in a different lexical scope or a global.
+ if (!Var)
+ continue;
+
+ // Already handled.
+ if (Visited.count(Var))
+ continue;
+
+ // Add to Result if all dependencies are visited.
+ if (visitedAllDependencies) {
+ Visited.insert(Var);
+ Result.push_back(Var);
+ continue;
+ }
+
+ // Detect cycles.
+ auto Res = Visiting.insert(Var);
+ if (!Res.second) {
+ assert(false && "dependency cycle in local variables");
+ return Result;
+ }
+
+ // Push dependencies and this node onto the worklist, so that this node is
+ // visited again after all of its dependencies are handled.
+ WorkList.push_back({Var, 1});
+ for (auto *Dependency : dependencies(Var)) {
+ auto Dep = dyn_cast_or_null<const DILocalVariable>(Dependency);
+ WorkList.push_back({DbgVar[Dep], 0});
+ }
+ }
+ return Result;
}
DIE *DwarfCompileUnit::createScopeChildrenDIE(LexicalScope *Scope,
@@ -601,8 +655,8 @@ DIE *DwarfCompileUnit::createScopeChildrenDIE(LexicalScope *Scope,
Children.push_back(constructVariableDIE(*DV.second, *Scope, ObjectPointer));
// Emit local variables.
- std::stable_sort(Vars.Locals.begin(), Vars.Locals.end(), sortLocalVars);
- for (DbgVariable *DV : Vars.Locals)
+ auto Locals = sortLocalVars(Vars.Locals);
+ for (DbgVariable *DV : Locals)
Children.push_back(constructVariableDIE(*DV, *Scope, ObjectPointer));
// Skip imported directives in gmlt-like data.
OpenPOWER on IntegriCloud