/// dump - Print data structures to dbgs().
void dump();
+ /// getOrCreateAbstractScope - Find or create an abstract lexical scope.
+ LexicalScope *getOrCreateAbstractScope(const MDNode *N);
+
private:
/// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If
/// not available then create new lexical scope.
/// getOrCreateInlinedScope - Find or create an inlined lexical scope.
LexicalScope *getOrCreateInlinedScope(MDNode *Scope, MDNode *InlinedAt);
- /// getOrCreateAbstractScope - Find or create an abstract lexical scope.
- LexicalScope *getOrCreateAbstractScope(const MDNode *N);
-
/// extractLexicalScopes - Extract instruction ranges for each lexical scopes
/// for the given machine function.
void extractLexicalScopes(SmallVectorImpl<InsnRange> &MIRanges,
return findAbstractVariable(DV, ScopeLoc.getScope(DV->getContext()));
}
-DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV,
- const MDNode *ScopeNode) {
+DbgVariable *DwarfDebug::getExistingAbstractVariable(DIVariable &DV,
+ DIVariable &Cleansed) {
LLVMContext &Ctx = DV->getContext();
// More then one inlined variable corresponds to one abstract variable.
- DIVariable Var = cleanseInlinedVariable(DV, Ctx);
- auto I = AbstractVariables.find(Var);
+ // FIXME: This duplication of variables when inlining should probably be
+ // removed. It's done to allow each DIVariable to describe its location
+ // because the DebugLoc on the dbg.value/declare isn't accurate. We should
+ // make it accurate then remove this duplication/cleansing stuff.
+ Cleansed = cleanseInlinedVariable(DV, Ctx);
+ auto I = AbstractVariables.find(Cleansed);
if (I != AbstractVariables.end())
return I->second.get();
+ return nullptr;
+}
- LexicalScope *Scope = LScopes.findAbstractScope(ScopeNode);
- if (!Scope)
- return nullptr;
-
+DbgVariable *DwarfDebug::createAbstractVariable(DIVariable &Var,
+ LexicalScope *Scope) {
auto AbsDbgVariable = make_unique<DbgVariable>(Var, nullptr, this);
addScopeVariable(Scope, AbsDbgVariable.get());
return (AbstractVariables[Var] = std::move(AbsDbgVariable)).get();
}
+DbgVariable *DwarfDebug::getOrCreateAbstractVariable(DIVariable &DV,
+ const MDNode *ScopeNode) {
+ DIVariable Cleansed = DV;
+ if (DbgVariable *Var = getExistingAbstractVariable(DV, Cleansed))
+ return Var;
+
+ return createAbstractVariable(Cleansed,
+ LScopes.getOrCreateAbstractScope(ScopeNode));
+}
+
+DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV,
+ const MDNode *ScopeNode) {
+ DIVariable Cleansed = DV;
+ if (DbgVariable *Var = getExistingAbstractVariable(DV, Cleansed))
+ return Var;
+
+ if (LexicalScope *Scope = LScopes.findAbstractScope(ScopeNode))
+ return createAbstractVariable(Cleansed, Scope);
+ return nullptr;
+}
+
// If Var is a current function argument then add it to CurrentFnArguments list.
bool DwarfDebug::addCurrentFnArgument(DbgVariable *Var, LexicalScope *Scope) {
if (!LScopes.isCurrentFunctionScope(Scope))
assert(DV && DV.isVariable());
if (!ProcessedVars.insert(DV))
continue;
- findAbstractVariable(DV, DV.getContext());
+ getOrCreateAbstractVariable(DV, DV.getContext());
}
constructAbstractSubprogramScopeDIE(TheCU, AScope);
}
}
/// \brief Find abstract variable associated with Var.
+ DbgVariable *getExistingAbstractVariable(DIVariable &DV,
+ DIVariable &Cleansed);
+ DbgVariable *createAbstractVariable(DIVariable &DV, LexicalScope *Scope);
+ DbgVariable *getOrCreateAbstractVariable(DIVariable &Var,
+ const MDNode *Scope);
DbgVariable *findAbstractVariable(DIVariable &Var, DebugLoc Loc);
DbgVariable *findAbstractVariable(DIVariable &Var, const MDNode *Scope);
// Define variable debug information entry.
auto VariableDie = make_unique<DIE>(DV.getTag());
DbgVariable *AbsVar = DV.getAbstractVariable();
- // FIXME: any missing abstract variable missing a DIE will result in incorrect
- // DWARF. More details in test/DebugInfo/missing-abstract-variable.ll for an
- // example of why this is happening.
- if (AbsVar && AbsVar->getDIE())
+ if (AbsVar) {
+ assert(AbsVar->getDIE());
addDIEEntry(*VariableDie, dwarf::DW_AT_abstract_origin, *AbsVar->getDIE());
- else {
+ } else {
if (!Name.empty())
addString(*VariableDie, dwarf::DW_AT_name, Name);
addSourceLine(*VariableDie, DV.getVariable());
; CHECK: [[ABS_B:.*]]: DW_TAG_formal_parameter
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}} "b"
-; FIXME: Missing 'x's local 's' variable.
+; CHECK-NOT: {{DW_TAG|NULL}}
+; CHECK: DW_TAG_lexical_block
+; CHECK-NOT: {{DW_TAG|NULL}}
+; CHECK: DW_TAG_lexical_block
+; CHECK-NOT: {{DW_TAG|NULL}}
+; CHECK: [[ABS_S:.*]]: DW_TAG_variable
+; CHECK-NOT: DW_TAG
+; CHECK: DW_AT_name {{.*}} "s"
; CHECK: DW_TAG_subprogram
; CHECK-NOT: DW_TAG
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_abstract_origin {{.*}} {[[ABS_X]]}
; CHECK-NOT: {{DW_TAG|NULL}}
-; FIXME: This formal parameter goes missing at least at -O2, maybe before that.
+; FIXME: This formal parameter goes missing at least at -O2 (& on
+; mips/powerpc), maybe before that. Perhaps SelectionDAG is to blame (and
+; fastisel succeeds).
; CHECK: DW_TAG_formal_parameter
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_abstract_origin {{.*}} {[[ABS_B]]}
; The two lexical blocks here are caused by the scope of the if that includes
; the condition variable, and the scope within the if's composite statement. I'm
-; not sure we really need both of them.
+; not sure we really need both of them since there's no variable declared in the
+; outer of the two
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_lexical_block
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_variable
; CHECK-NOT: DW_TAG
-
-; FIXME: This shouldn't have a name here, it should use DW_AT_abstract_origin
-; to reference an abstract variable definition instead
-
-; CHECK: DW_AT_name {{.*}} "s"
-
+; CHECK: DW_AT_abstract_origin {{.*}} {[[ABS_S]]}
@t = external global i32