1
0
mirror of https://github.com/c64scene-ar/llvm-6502.git synced 2025-02-24 12:29:33 +00:00

Collect and coalesce DBG_VALUE instructions before emitting the function.

Correctly terminate the range of register DBG_VALUEs when the register is
clobbered or when the basic block ends.

The code is now ready to deal with variables that are sometimes in a register
and sometimes on the stack. We just need to teach emitDebugLoc to say 'stack
slot'.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128327 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen 2011-03-26 02:19:36 +00:00
parent eca915fb52
commit adb877d62e
4 changed files with 192 additions and 111 deletions
include/llvm/CodeGen
lib/CodeGen/AsmPrinter
test/CodeGen/X86

@ -309,6 +309,10 @@ public:
/// instruction in the basic block, or end()
iterator getLastNonDebugInstr();
const_iterator getLastNonDebugInstr() const {
return const_cast<MachineBasicBlock*>(this)->getLastNonDebugInstr();
}
/// SplitCriticalEdge - Split the critical edge from this block to the
/// given successor block, and return the newly created block, or null
/// if splitting is not possible.

@ -2408,38 +2408,21 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
/// collection info from MMI table.
collectVariableInfoFromMMITable(MF, Processed);
SmallVector<const MachineInstr *, 8> DbgValues;
// Collect variable information from DBG_VALUE machine instructions;
for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end();
I != E; ++I)
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
II != IE; ++II) {
const MachineInstr *MInsn = II;
if (!MInsn->isDebugValue())
continue;
DbgValues.push_back(MInsn);
}
// This is a collection of DBG_VALUE instructions describing same variable.
SmallVector<const MachineInstr *, 4> MultipleValues;
for(SmallVector<const MachineInstr *, 8>::iterator I = DbgValues.begin(),
E = DbgValues.end(); I != E; ++I) {
const MachineInstr *MInsn = *I;
MultipleValues.clear();
if (isDbgValueInDefinedReg(MInsn))
MultipleValues.push_back(MInsn);
DIVariable DV(MInsn->getOperand(MInsn->getNumOperands() - 1).getMetadata());
if (Processed.count(DV) != 0)
for (SmallVectorImpl<const MDNode*>::const_iterator
UVI = UserVariables.begin(), UVE = UserVariables.end(); UVI != UVE;
++UVI) {
const MDNode *Var = *UVI;
if (Processed.count(Var))
continue;
for (SmallVector<const MachineInstr *, 8>::iterator MI = I+1,
ME = DbgValues.end(); MI != ME; ++MI) {
const MDNode *Var =
(*MI)->getOperand((*MI)->getNumOperands()-1).getMetadata();
if (Var == DV)
MultipleValues.push_back(*MI);
}
// History contains relevant DBG_VALUE instructions for Var and instructions
// clobbering it.
SmallVectorImpl<const MachineInstr*> &History = DbgValues[Var];
if (History.empty())
continue;
const MachineInstr *MInsn = History.front();
DIVariable DV(Var);
DbgScope *Scope = NULL;
if (DV.getTag() == dwarf::DW_TAG_arg_variable &&
DISubprogram(DV.getContext()).describes(MF->getFunction()))
@ -2451,6 +2434,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
continue;
Processed.insert(DV);
assert(MInsn->isDebugValue() && "History must begin with debug value");
DbgVariable *RegVar = new DbgVariable(DV);
if (!addCurrentFnArgument(MF, RegVar, Scope))
Scope->addVariable(RegVar);
@ -2458,21 +2442,21 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
DbgVariableToDbgInstMap[AbsVar] = MInsn;
VarToAbstractVarMap[RegVar] = AbsVar;
}
if (MultipleValues.size() <= 1 && !RegClobberInsn.count(MInsn)) {
// Simple ranges that are fully coalesced.
if (History.size() <= 1 || (History.size() == 2 &&
MInsn->isIdenticalTo(History.back()))) {
DbgVariableToDbgInstMap[RegVar] = MInsn;
continue;
}
// handle multiple DBG_VALUE instructions describing one variable.
if (DotDebugLocEntries.empty())
RegVar->setDotDebugLocOffset(0);
else
RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());
RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());
for (SmallVector<const MachineInstr *, 4>::iterator
MVI = MultipleValues.begin(), MVE = MultipleValues.end();
MVI != MVE; ++MVI) {
const MachineInstr *Begin = *MVI;
for (SmallVectorImpl<const MachineInstr*>::const_iterator
HI = History.begin(), HE = History.end(); HI != HE; ++HI) {
const MachineInstr *Begin = *HI;
assert(Begin->isDebugValue() && "Invalid History entry");
MachineLocation MLoc;
if (Begin->getNumOperands() == 3) {
if (Begin->getOperand(0).isReg() && Begin->getOperand(1).isImm())
@ -2480,6 +2464,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
} else
MLoc = Asm->getDebugValueLocation(Begin);
// FIXME: emitDebugLoc only understands registers.
if (!MLoc.getReg())
continue;
@ -2487,17 +2472,23 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
const MCSymbol *FLabel = getLabelBeforeInsn(Begin);
const MCSymbol *SLabel = 0;
if (const MachineInstr *ClobberMI = RegClobberInsn.lookup(Begin))
// The register range starting at Begin may be clobbered.
SLabel = getLabelAfterInsn(ClobberMI);
else if (MVI + 1 == MVE)
// If Begin is the last instruction then its value is valid
if (HI + 1 == HE)
// If Begin is the last instruction in History then its value is valid
// until the end of the funtion.
SLabel = FunctionEndSym;
else
// The value is valid until the next DBG_VALUE.
SLabel = getLabelBeforeInsn(MVI[1]);
else {
const MachineInstr *End = HI[1];
if (End->isDebugValue())
SLabel = getLabelBeforeInsn(End);
else {
// End is a normal instruction clobbering the range.
SLabel = getLabelAfterInsn(End);
assert(SLabel && "Forgot label after clobber instruction");
++HI;
}
}
// The value is valid until the next DBG_VALUE or clobber.
DotDebugLocEntries.push_back(DotDebugLocEntry(FLabel, SLabel, MLoc));
}
DotDebugLocEntries.push_back(DotDebugLocEntry());
@ -2519,21 +2510,14 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
/// getLabelBeforeInsn - Return Label preceding the instruction.
const MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) {
DenseMap<const MachineInstr *, MCSymbol *>::iterator I =
LabelsBeforeInsn.find(MI);
if (I == LabelsBeforeInsn.end())
// FunctionBeginSym always preceeds all the instruction in current function.
return FunctionBeginSym;
return I->second;
MCSymbol *Label = LabelsBeforeInsn.lookup(MI);
assert(Label && "Didn't insert label before instruction");
return Label;
}
/// getLabelAfterInsn - Return Label immediately following the instruction.
const MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) {
DenseMap<const MachineInstr *, MCSymbol *>::iterator I =
LabelsAfterInsn.find(MI);
if (I == LabelsAfterInsn.end())
return NULL;
return I->second;
return LabelsAfterInsn.lookup(MI);
}
/// beginInstruction - Process beginning of an instruction.
@ -2552,14 +2536,22 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
}
// Insert labels where requested.
if (!InsnNeedsLabel.count(MI))
DenseMap<const MachineInstr*, MCSymbol*>::iterator I =
LabelsBeforeInsn.find(MI);
// No label needed.
if (I == LabelsBeforeInsn.end())
return;
// Label already assigned.
if (I->second)
return;
if (!PrevLabel) {
PrevLabel = MMI->getContext().CreateTempSymbol();
Asm->OutStreamer.EmitLabel(PrevLabel);
}
LabelsBeforeInsn[MI] = PrevLabel;
I->second = PrevLabel;
}
/// endInstruction - Process end of an instruction.
@ -2569,7 +2561,15 @@ void DwarfDebug::endInstruction(const MachineInstr *MI) {
if (!MI->isDebugValue())
PrevLabel = 0;
if (!InsnsNeedsLabelAfter.count(MI))
DenseMap<const MachineInstr*, MCSymbol*>::iterator I =
LabelsAfterInsn.find(MI);
// No label needed.
if (I == LabelsAfterInsn.end())
return;
// Label already assigned.
if (I->second)
return;
// We need a label after this instruction.
@ -2577,7 +2577,7 @@ void DwarfDebug::endInstruction(const MachineInstr *MI) {
PrevLabel = MMI->getContext().CreateTempSymbol();
Asm->OutStreamer.EmitLabel(PrevLabel);
}
LabelsAfterInsn[MI] = PrevLabel;
I->second = PrevLabel;
}
/// getOrCreateDbgScope - Create DbgScope for the scope.
@ -2837,8 +2837,8 @@ void DwarfDebug::identifyScopeMarkers() {
RE = Ranges.end(); RI != RE; ++RI) {
assert(RI->first && "DbgRange does not have first instruction!");
assert(RI->second && "DbgRange does not have second instruction!");
InsnNeedsLabel.insert(RI->first);
InsnsNeedsLabelAfter.insert(RI->second);
requestLabelBeforeInsn(RI->first);
requestLabelAfterInsn(RI->second);
}
}
}
@ -2916,46 +2916,78 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
recordSourceLine(Line, Col, TheScope);
assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't cleaned");
/// ProcessedArgs - Collection of arguments already processed.
SmallPtrSet<const MDNode *, 8> ProcessedArgs;
/// LastDbgValue - Refer back to the last DBG_VALUE instruction to mention MD.
DenseMap<const MDNode*, const MachineInstr*> LastDbgValue;
const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo();
/// LiveUserVar - Map physreg numbers to the MDNode they contain.
std::vector<const MDNode*> LiveUserVar(TRI->getNumRegs());
for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
I != E; ++I)
I != E; ++I) {
bool AtBlockEntry = true;
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
II != IE; ++II) {
const MachineInstr *MI = II;
DebugLoc DL = MI->getDebugLoc();
if (MI->isDebugValue()) {
assert (MI->getNumOperands() > 1 && "Invalid machine instruction!");
// Keep track of variables in registers.
// Keep track of user variables.
const MDNode *Var =
MI->getOperand(MI->getNumOperands() - 1).getMetadata();
LastDbgValue[Var] = MI;
// Variable is in a register, we need to check for clobbers.
if (isDbgValueInDefinedReg(MI))
LiveUserVar[MI->getOperand(0).getReg()] = Var;
DIVariable DV(Var);
if (!DV.Verify()) continue;
// If DBG_VALUE is for a local variable then it needs a label.
if (DV.getTag() != dwarf::DW_TAG_arg_variable)
InsnNeedsLabel.insert(MI);
// DBG_VALUE for inlined functions argument needs a label.
else if (!DISubprogram(getDISubprogram(DV.getContext())).
describes(MF->getFunction()))
InsnNeedsLabel.insert(MI);
// DBG_VALUE indicating argument location change needs a label.
else if (!ProcessedArgs.insert(DV))
InsnNeedsLabel.insert(MI);
// Check the history of this variable.
SmallVectorImpl<const MachineInstr*> &History = DbgValues[Var];
if (History.empty()) {
UserVariables.push_back(Var);
// The first mention of a function argument gets the FunctionBeginSym
// label, so arguments are visible when breaking at function entry.
DIVariable DV(Var);
if (DV.Verify() && DV.getTag() == dwarf::DW_TAG_arg_variable &&
DISubprogram(getDISubprogram(DV.getContext()))
.describes(MF->getFunction()))
LabelsBeforeInsn[MI] = FunctionBeginSym;
} else {
// We have seen this variable before. Try to coalesce DBG_VALUEs.
const MachineInstr *Prev = History.back();
if (Prev->isDebugValue()) {
// Coalesce identical entries at the end of History.
if (History.size() >= 2 &&
Prev->isIdenticalTo(History[History.size() - 2]))
History.pop_back();
// Terminate old register assignments that don't reach MI;
MachineFunction::const_iterator PrevMBB = Prev->getParent();
if (PrevMBB != I && (!AtBlockEntry || llvm::next(PrevMBB) != I) &&
isDbgValueInDefinedReg(Prev)) {
// Previous register assignment needs to terminate at the end of
// its basic block.
MachineBasicBlock::const_iterator LastMI =
PrevMBB->getLastNonDebugInstr();
if (LastMI == PrevMBB->end())
// Drop DBG_VALUE for empty range.
History.pop_back();
else {
// Terminate after LastMI.
History.push_back(LastMI);
}
}
}
}
History.push_back(MI);
} else {
// Not a DBG_VALUE instruction.
if (!MI->isLabel())
AtBlockEntry = false;
// Check if the instruction clobbers any registers with debug vars.
for (MachineInstr::const_mop_iterator MOI = MI->operands_begin(),
MOE = MI->operands_end(); MOI != MOE; ++MOI) {
@ -2970,19 +3002,57 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
LiveUserVar[Reg] = 0;
// Was MD last defined by a DBG_VALUE referring to Reg?
const MachineInstr *Last = LastDbgValue.lookup(Var);
if (!Last || Last->getParent() != MI->getParent())
DbgValueHistoryMap::iterator HistI = DbgValues.find(Var);
if (HistI == DbgValues.end())
continue;
if (!isDbgValueInDefinedReg(Last) ||
Last->getOperand(0).getReg() != Reg)
SmallVectorImpl<const MachineInstr*> &History = HistI->second;
if (History.empty())
continue;
// MD is clobbered. Make sure the next instruction gets a label.
InsnsNeedsLabelAfter.insert(MI);
RegClobberInsn[Last] = MI;
const MachineInstr *Prev = History.back();
// Sanity-check: Register assignments are terminated at the end of
// their block.
if (!Prev->isDebugValue() || Prev->getParent() != MI->getParent())
continue;
// Is the variable still in Reg?
if (!isDbgValueInDefinedReg(Prev) ||
Prev->getOperand(0).getReg() != Reg)
continue;
// Var is clobbered. Make sure the next instruction gets a label.
History.push_back(MI);
}
}
}
}
}
for (DbgValueHistoryMap::iterator I = DbgValues.begin(), E = DbgValues.end();
I != E; ++I) {
SmallVectorImpl<const MachineInstr*> &History = I->second;
if (History.empty())
continue;
// Make sure the final register assignments are terminated.
const MachineInstr *Prev = History.back();
if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) {
const MachineBasicBlock *PrevMBB = Prev->getParent();
MachineBasicBlock::const_iterator LastMI = PrevMBB->getLastNonDebugInstr();
if (LastMI == PrevMBB->end())
// Drop DBG_VALUE for empty range.
History.pop_back();
else {
// Terminate after LastMI.
History.push_back(LastMI);
}
}
// Request labels for the full history.
for (unsigned i = 0, e = History.size(); i != e; ++i) {
const MachineInstr *MI = History[i];
if (MI->isDebugValue())
requestLabelBeforeInsn(MI);
else
requestLabelAfterInsn(MI);
}
}
PrevInstLoc = DebugLoc();
PrevLabel = FunctionBeginSym;
@ -3043,13 +3113,12 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
// Clear debug info
CurrentFnDbgScope = NULL;
CurrentFnArguments.clear();
InsnNeedsLabel.clear();
DbgVariableToFrameIndexMap.clear();
VarToAbstractVarMap.clear();
DbgVariableToDbgInstMap.clear();
DeleteContainerSeconds(DbgScopeMap);
InsnsNeedsLabelAfter.clear();
RegClobberInsn.clear();
UserVariables.clear();
DbgValues.clear();
ConcreteScopes.clear();
DeleteContainerSeconds(AbstractScopes);
AbstractScopesList.clear();

@ -218,19 +218,16 @@ class DwarfDebug {
/// instruction.
DenseMap<const MachineInstr *, MCSymbol *> LabelsAfterInsn;
/// insnNeedsLabel - Collection of instructions that need a label to mark
/// a debuggging information entity.
SmallPtrSet<const MachineInstr *, 8> InsnNeedsLabel;
/// UserVariables - Every user variable mentioned by a DBG_VALUE instruction
/// in order of appearance.
SmallVector<const MDNode*, 8> UserVariables;
/// InsnsNeedsLabelAfter - Collection of instructions that need a label after
/// the instruction because they end a scope of clobber a register.
SmallPtrSet<const MachineInstr *, 8> InsnsNeedsLabelAfter;
/// RegClobberInsn - For each DBG_VALUE instruction referring to a register
/// that is clobbered before the variable gets a new DBG_VALUE, map the
/// instruction that clobbered the register. This instruction will also be in
/// InsnsNeedsLabelAfter.
DenseMap<const MachineInstr *, const MachineInstr *> RegClobberInsn;
/// DbgValues - For each user variable, keep a list of DBG_VALUE
/// instructions in order. The list can also contain normal instructions that
/// clobber the previous DBG_VALUE.
typedef DenseMap<const MDNode*, SmallVector<const MachineInstr*, 4> >
DbgValueHistoryMap;
DbgValueHistoryMap DbgValues;
SmallVector<const MCSymbol *, 8> DebugRangeSymbols;
@ -570,6 +567,23 @@ private:
/// side table maintained by MMI.
void collectVariableInfoFromMMITable(const MachineFunction * MF,
SmallPtrSet<const MDNode *, 16> &P);
/// requestLabelBeforeInsn - Ensure that a label will be emitted before MI.
void requestLabelBeforeInsn(const MachineInstr *MI) {
LabelsBeforeInsn.insert(std::make_pair(MI, (MCSymbol*)0));
}
/// getLabelBeforeInsn - Return Label preceding the instruction.
const MCSymbol *getLabelBeforeInsn(const MachineInstr *MI);
/// requestLabelAfterInsn - Ensure that a label will be emitted after MI.
void requestLabelAfterInsn(const MachineInstr *MI) {
LabelsAfterInsn.insert(std::make_pair(MI, (MCSymbol*)0));
}
/// getLabelAfterInsn - Return Label immediately following the instruction.
const MCSymbol *getLabelAfterInsn(const MachineInstr *MI);
public:
//===--------------------------------------------------------------------===//
// Main entry points.
@ -593,12 +607,6 @@ public:
///
void endFunction(const MachineFunction *MF);
/// getLabelBeforeInsn - Return Label preceding the instruction.
const MCSymbol *getLabelBeforeInsn(const MachineInstr *MI);
/// getLabelAfterInsn - Return Label immediately following the instruction.
const MCSymbol *getLabelAfterInsn(const MachineInstr *MI);
/// beginInstruction - Process beginning of an instruction.
void beginInstruction(const MachineInstr *MI);

@ -4,7 +4,7 @@ target triple = "x86_64-apple-darwin8"
;CHECK: Ldebug_loc0:
;CHECK-NEXT: .quad Lfunc_begin0
;CHECK-NEXT: .quad Lfunc_end0
;CHECK-NEXT: .quad L
;CHECK-NEXT: .short 1 ## Loc expr size
;CHECK-NEXT: .byte 85 ## DW_OP_reg5
;CHECK-NEXT: .quad 0