mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-01 00:33:09 +00:00
Move logic for calculating DBG_VALUE history map into separate file/class.
Summary: No functionality change. Test Plan: llvm regression test suite. Reviewers: dblaikie Reviewed By: dblaikie Subscribers: echristo, llvm-commits Differential Revision: http://reviews.llvm.org/D3573 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207708 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d96bbedc6a
commit
d51ae64368
@ -4,6 +4,7 @@ add_llvm_library(LLVMAsmPrinter
|
||||
AsmPrinter.cpp
|
||||
AsmPrinterDwarf.cpp
|
||||
AsmPrinterInlineAsm.cpp
|
||||
DbgValueHistoryCalculator.cpp
|
||||
DIE.cpp
|
||||
DIEHash.cpp
|
||||
DwarfAccelTable.cpp
|
||||
|
152
lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
Normal file
152
lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
//===-- llvm/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp -------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DbgValueHistoryCalculator.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
|
||||
#define DEBUG_TYPE "dwarfdebug"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// Return true if debug value, encoded by DBG_VALUE instruction, is in a
|
||||
// defined reg.
|
||||
static bool isDbgValueInDefinedReg(const MachineInstr *MI) {
|
||||
assert(MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!");
|
||||
return MI->getNumOperands() == 3 && MI->getOperand(0).isReg() &&
|
||||
MI->getOperand(0).getReg() &&
|
||||
(MI->getOperand(1).isImm() ||
|
||||
(MI->getOperand(1).isReg() && MI->getOperand(1).getReg() == 0U));
|
||||
}
|
||||
|
||||
void calculateDbgValueHistory(const MachineFunction *MF,
|
||||
const TargetRegisterInfo *TRI,
|
||||
DbgValueHistoryMap &Result) {
|
||||
// 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) {
|
||||
bool AtBlockEntry = true;
|
||||
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
|
||||
II != IE; ++II) {
|
||||
const MachineInstr *MI = II;
|
||||
|
||||
if (MI->isDebugValue()) {
|
||||
assert(MI->getNumOperands() > 1 && "Invalid machine instruction!");
|
||||
|
||||
// Keep track of user variables.
|
||||
const MDNode *Var = MI->getDebugVariable();
|
||||
|
||||
// Variable is in a register, we need to check for clobbers.
|
||||
if (isDbgValueInDefinedReg(MI))
|
||||
LiveUserVar[MI->getOperand(0).getReg()] = Var;
|
||||
|
||||
// Check the history of this variable.
|
||||
SmallVectorImpl<const MachineInstr *> &History = Result[Var];
|
||||
if (!History.empty()) {
|
||||
// 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])) {
|
||||
DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n"
|
||||
<< "\t" << *Prev << "\t"
|
||||
<< *History[History.size() - 2] << "\n");
|
||||
History.pop_back();
|
||||
}
|
||||
|
||||
// Terminate old register assignments that don't reach MI;
|
||||
MachineFunction::const_iterator PrevMBB = Prev->getParent();
|
||||
if (PrevMBB != I && (!AtBlockEntry || std::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.
|
||||
DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n"
|
||||
<< "\t" << *Prev << "\n");
|
||||
History.pop_back();
|
||||
} else if (std::next(PrevMBB) != PrevMBB->getParent()->end())
|
||||
// Terminate after LastMI.
|
||||
History.push_back(LastMI);
|
||||
}
|
||||
}
|
||||
}
|
||||
History.push_back(MI);
|
||||
} else {
|
||||
// Not a DBG_VALUE instruction.
|
||||
if (!MI->isPosition())
|
||||
AtBlockEntry = false;
|
||||
|
||||
// Check if the instruction clobbers any registers with debug vars.
|
||||
for (const MachineOperand &MO : MI->operands()) {
|
||||
if (!MO.isReg() || !MO.isDef() || !MO.getReg())
|
||||
continue;
|
||||
for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();
|
||||
++AI) {
|
||||
unsigned Reg = *AI;
|
||||
const MDNode *Var = LiveUserVar[Reg];
|
||||
if (!Var)
|
||||
continue;
|
||||
// Reg is now clobbered.
|
||||
LiveUserVar[Reg] = nullptr;
|
||||
|
||||
// Was MD last defined by a DBG_VALUE referring to Reg?
|
||||
auto HistI = Result.find(Var);
|
||||
if (HistI == Result.end())
|
||||
continue;
|
||||
SmallVectorImpl<const MachineInstr *> &History = HistI->second;
|
||||
if (History.empty())
|
||||
continue;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the final register assignments are terminated.
|
||||
for (auto &I : Result) {
|
||||
SmallVectorImpl<const MachineInstr *> &History = I.second;
|
||||
if (History.empty())
|
||||
continue;
|
||||
|
||||
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 if (PrevMBB != &PrevMBB->getParent()->back()) {
|
||||
// Terminate after LastMI.
|
||||
History.push_back(LastMI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
34
lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h
Normal file
34
lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h
Normal file
@ -0,0 +1,34 @@
|
||||
//===-- llvm/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h ----*- C++ -*--===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H_
|
||||
#define CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H_
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MachineFunction;
|
||||
class MachineInstr;
|
||||
class MDNode;
|
||||
class TargetRegisterInfo;
|
||||
|
||||
// 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;
|
||||
|
||||
void calculateDbgValueHistory(const MachineFunction *MF,
|
||||
const TargetRegisterInfo *TRI,
|
||||
DbgValueHistoryMap &Result);
|
||||
}
|
||||
|
||||
#endif
|
@ -1158,16 +1158,6 @@ void DwarfDebug::collectVariableInfoFromMMITable(
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if debug value, encoded by DBG_VALUE instruction, is in a
|
||||
// defined reg.
|
||||
static bool isDbgValueInDefinedReg(const MachineInstr *MI) {
|
||||
assert(MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!");
|
||||
return MI->getNumOperands() == 3 && MI->getOperand(0).isReg() &&
|
||||
MI->getOperand(0).getReg() &&
|
||||
(MI->getOperand(1).isImm() ||
|
||||
(MI->getOperand(1).isReg() && MI->getOperand(1).getReg() == 0U));
|
||||
}
|
||||
|
||||
// Get .debug_loc entry for the instruction range starting at MI.
|
||||
static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) {
|
||||
const MDNode *Var = MI->getDebugVariable();
|
||||
@ -1449,138 +1439,47 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
|
||||
// Assumes in correct section after the entry point.
|
||||
Asm->OutStreamer.EmitLabel(FunctionBeginSym);
|
||||
|
||||
const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo();
|
||||
// LiveUserVar - Map physreg numbers to the MDNode they contain.
|
||||
std::vector<const MDNode *> LiveUserVar(TRI->getNumRegs());
|
||||
|
||||
// Collect user variables, find the end of the prologue.
|
||||
for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E;
|
||||
++I) {
|
||||
bool AtBlockEntry = true;
|
||||
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
|
||||
II != IE; ++II) {
|
||||
const MachineInstr *MI = II;
|
||||
|
||||
if (MI->isDebugValue()) {
|
||||
assert(MI->getNumOperands() > 1 && "Invalid machine instruction!");
|
||||
|
||||
// Keep track of user variables.
|
||||
// Keep track of user variables in order of appearance. Store the set
|
||||
// of variables we've already seen as a set of keys in DbgValues.
|
||||
const MDNode *Var = MI->getDebugVariable();
|
||||
|
||||
// Variable is in a register, we need to check for clobbers.
|
||||
if (isDbgValueInDefinedReg(MI))
|
||||
LiveUserVar[MI->getOperand(0).getReg()] = Var;
|
||||
|
||||
// Check the history of this variable.
|
||||
SmallVectorImpl<const MachineInstr *> &History = DbgValues[Var];
|
||||
if (History.empty()) {
|
||||
auto IterPair = DbgValues.insert(
|
||||
std::make_pair(Var, SmallVector<const MachineInstr *, 4>()));
|
||||
if (IterPair.second)
|
||||
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.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable &&
|
||||
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])) {
|
||||
DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n"
|
||||
<< "\t" << *Prev << "\t"
|
||||
<< *History[History.size() - 2] << "\n");
|
||||
History.pop_back();
|
||||
}
|
||||
|
||||
// Terminate old register assignments that don't reach MI;
|
||||
MachineFunction::const_iterator PrevMBB = Prev->getParent();
|
||||
if (PrevMBB != I && (!AtBlockEntry || std::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.
|
||||
DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n"
|
||||
<< "\t" << *Prev << "\n");
|
||||
History.pop_back();
|
||||
} else if (std::next(PrevMBB) != PrevMBB->getParent()->end())
|
||||
// Terminate after LastMI.
|
||||
History.push_back(LastMI);
|
||||
}
|
||||
}
|
||||
}
|
||||
History.push_back(MI);
|
||||
} else {
|
||||
// Not a DBG_VALUE instruction.
|
||||
if (!MI->isPosition())
|
||||
AtBlockEntry = false;
|
||||
|
||||
// First known non-DBG_VALUE and non-frame setup location marks
|
||||
// the beginning of the function body.
|
||||
if (!MI->getFlag(MachineInstr::FrameSetup) &&
|
||||
(PrologEndLoc.isUnknown() && !MI->getDebugLoc().isUnknown()))
|
||||
PrologEndLoc = MI->getDebugLoc();
|
||||
|
||||
// Check if the instruction clobbers any registers with debug vars.
|
||||
for (const MachineOperand &MO : MI->operands()) {
|
||||
if (!MO.isReg() || !MO.isDef() || !MO.getReg())
|
||||
continue;
|
||||
for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();
|
||||
++AI) {
|
||||
unsigned Reg = *AI;
|
||||
const MDNode *Var = LiveUserVar[Reg];
|
||||
if (!Var)
|
||||
continue;
|
||||
// Reg is now clobbered.
|
||||
LiveUserVar[Reg] = nullptr;
|
||||
|
||||
// Was MD last defined by a DBG_VALUE referring to Reg?
|
||||
DbgValueHistoryMap::iterator HistI = DbgValues.find(Var);
|
||||
if (HistI == DbgValues.end())
|
||||
continue;
|
||||
SmallVectorImpl<const MachineInstr *> &History = HistI->second;
|
||||
if (History.empty())
|
||||
continue;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate history for local variables.
|
||||
calculateDbgValueHistory(MF, Asm->TM.getRegisterInfo(), DbgValues);
|
||||
|
||||
// Request labels for the full history.
|
||||
for (auto &I : DbgValues) {
|
||||
SmallVectorImpl<const MachineInstr *> &History = I.second;
|
||||
const 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 if (PrevMBB != &PrevMBB->getParent()->back()) {
|
||||
// Terminate after LastMI.
|
||||
History.push_back(LastMI);
|
||||
}
|
||||
}
|
||||
// Request labels for the full history.
|
||||
// The first mention of a function argument gets the FunctionBeginSym
|
||||
// label, so arguments are visible when breaking at function entry.
|
||||
DIVariable DV(I.first);
|
||||
if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable &&
|
||||
getDISubprogram(DV.getContext()).describes(MF->getFunction()))
|
||||
LabelsBeforeInsn[History.front()] = FunctionBeginSym;
|
||||
|
||||
for (const MachineInstr *MI : History) {
|
||||
if (MI->isDebugValue())
|
||||
requestLabelBeforeInsn(MI);
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "DwarfFile.h"
|
||||
#include "AsmPrinterHandler.h"
|
||||
#include "DIE.h"
|
||||
#include "DbgValueHistoryCalculator.h"
|
||||
#include "DebugLocEntry.h"
|
||||
#include "DebugLocList.h"
|
||||
#include "DwarfAccelTable.h"
|
||||
@ -222,11 +223,7 @@ class DwarfDebug : public AsmPrinterHandler {
|
||||
// appearance.
|
||||
SmallVector<const MDNode *, 8> UserVariables;
|
||||
|
||||
// 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;
|
||||
// History of DBG_VALUE and clobber instructions for each user variable.
|
||||
DbgValueHistoryMap DbgValues;
|
||||
|
||||
// Previous instruction's location information. This is used to determine
|
||||
|
Loading…
Reference in New Issue
Block a user