Add DBG_VALUE handling for byval parameters; this

produces a comment on targets that support it, but
the Dwarf writer is not hooked up yet.

llvm-svn: 102372
This commit is contained in:
Dale Johannesen 2010-04-26 20:06:49 +00:00
parent bc41cfa78f
commit e098352ed1
4 changed files with 106 additions and 31 deletions

View File

@ -62,8 +62,15 @@ private:
/// instead the info is kept off to the side in this structure. Each SDNode may
/// have one or more associated dbg_value entries. This information is kept in
/// DbgValMap.
/// Byval parameters are handled separately because they don't use alloca's,
/// which busts the normal mechanism. There is good reason for handling all
/// parameters separately: they may not have code generated for them, they
/// should always go at the beginning of the function regardless of other code
/// motion, and debug info for them is potentially useful even if the parameter
/// is unused. Right now only byval parameters are handled separately.
class SDDbgInfo {
SmallVector<SDDbgValue*, 32> DbgValues;
SmallVector<SDDbgValue*, 32> ByvalParmDbgValues;
DenseMap<const SDNode*, SmallVector<SDDbgValue*, 2> > DbgValMap;
void operator=(const SDDbgInfo&); // Do not implement.
@ -71,19 +78,22 @@ class SDDbgInfo {
public:
SDDbgInfo() {}
void add(SDDbgValue *V, const SDNode *Node = 0) {
void add(SDDbgValue *V, const SDNode *Node, bool isParameter) {
if (isParameter) {
ByvalParmDbgValues.push_back(V);
} else DbgValues.push_back(V);
if (Node)
DbgValMap[Node].push_back(V);
DbgValues.push_back(V);
}
void clear() {
DbgValMap.clear();
DbgValues.clear();
ByvalParmDbgValues.clear();
}
bool empty() const {
return DbgValues.empty();
return DbgValues.empty() && ByvalParmDbgValues.empty();
}
SmallVector<SDDbgValue*,2> &getSDDbgValues(const SDNode *Node) {
@ -93,6 +103,8 @@ public:
typedef SmallVector<SDDbgValue*,32>::iterator DbgIterator;
DbgIterator DbgBegin() { return DbgValues.begin(); }
DbgIterator DbgEnd() { return DbgValues.end(); }
DbgIterator ByvalParmDbgBegin() { return ByvalParmDbgValues.begin(); }
DbgIterator ByvalParmDbgEnd() { return ByvalParmDbgValues.end(); }
};
enum CombineLevel {
@ -877,7 +889,7 @@ public:
/// AddDbgValue - Add a dbg_value SDNode. If SD is non-null that means the
/// value is produced by SD.
void AddDbgValue(SDDbgValue *DB, SDNode *SD = 0);
void AddDbgValue(SDDbgValue *DB, SDNode *SD, bool isParameter);
/// GetDbgValues - Get the debug values which reference the given SDNode.
SmallVector<SDDbgValue*,2> &GetDbgValues(const SDNode* SD) {
@ -890,6 +902,12 @@ public:
SDDbgInfo::DbgIterator DbgBegin() { return DbgInfo->DbgBegin(); }
SDDbgInfo::DbgIterator DbgEnd() { return DbgInfo->DbgEnd(); }
SDDbgInfo::DbgIterator ByvalParmDbgBegin() {
return DbgInfo->ByvalParmDbgBegin();
}
SDDbgInfo::DbgIterator ByvalParmDbgEnd() {
return DbgInfo->ByvalParmDbgEnd();
}
void dump() const;

View File

@ -470,6 +470,17 @@ EmitSchedule(DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) {
SmallSet<unsigned, 8> Seen;
bool HasDbg = DAG->hasDebugValues();
// If this is the first BB, emit byval parameter dbg_value's.
if (HasDbg && BB->getParent()->begin() == MachineFunction::iterator(BB)) {
SDDbgInfo::DbgIterator PDI = DAG->ByvalParmDbgBegin();
SDDbgInfo::DbgIterator PDE = DAG->ByvalParmDbgEnd();
for (; PDI != PDE; ++PDI) {
MachineInstr *DbgMI= Emitter.EmitDbgValue(*PDI, VRBaseMap, EM);
if (DbgMI)
BB->insert(BB->end(), DbgMI);
}
}
for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
SUnit *SU = Sequence[i];
if (!SU) {
@ -494,20 +505,20 @@ EmitSchedule(DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) {
SDNode *N = FlaggedNodes.back();
Emitter.EmitNode(FlaggedNodes.back(), SU->OrigNode != SU, SU->isCloned,
VRBaseMap, EM);
// Remember the the source order of the inserted instruction.
// Remember the source order of the inserted instruction.
if (HasDbg)
ProcessSourceNode(N, DAG, Emitter, EM, VRBaseMap, Orders, Seen);
FlaggedNodes.pop_back();
}
Emitter.EmitNode(SU->getNode(), SU->OrigNode != SU, SU->isCloned,
VRBaseMap, EM);
// Remember the the source order of the inserted instruction.
// Remember the source order of the inserted instruction.
if (HasDbg)
ProcessSourceNode(SU->getNode(), DAG, Emitter, EM, VRBaseMap, Orders,
Seen);
}
// Insert all the dbg_value which have not already been inserted in source
// Insert all the dbg_values which have not already been inserted in source
// order sequence.
if (HasDbg) {
MachineBasicBlock::iterator BBBegin = BB->empty() ? BB->end() : BB->begin();

View File

@ -5341,8 +5341,8 @@ unsigned SelectionDAG::GetOrdering(const SDNode *SD) const {
/// AddDbgValue - Add a dbg_value SDNode. If SD is non-null that means the
/// value is produced by SD.
void SelectionDAG::AddDbgValue(SDDbgValue *DB, SDNode *SD) {
DbgInfo->add(DB, SD);
void SelectionDAG::AddDbgValue(SDDbgValue *DB, SDNode *SD, bool isParameter) {
DbgInfo->add(DB, SD, isParameter);
if (SD)
SD->setHasDebugValue(true);
}

View File

@ -3775,32 +3775,75 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
case Intrinsic::dbg_declare: {
// FIXME: currently, we get here only if OptLevel != CodeGenOpt::None.
// The real handling of this intrinsic is in FastISel.
if (OptLevel != CodeGenOpt::None)
// if (OptLevel != CodeGenOpt::None)
// FIXME: Variable debug info is not supported here.
return 0;
// return 0;
const DbgDeclareInst &DI = cast<DbgDeclareInst>(I);
if (!DIDescriptor::ValidDebugInfo(DI.getVariable(), CodeGenOpt::None))
return 0;
MDNode *Variable = DI.getVariable();
// Parameters are handled specially.
bool isParameter = false;
ConstantInt *CI = dyn_cast_or_null<ConstantInt>(Variable->getOperand(0));
if (CI) {
unsigned Val = CI->getZExtValue();
unsigned Tag = Val & ~LLVMDebugVersionMask;
if (Tag == dwarf::DW_TAG_arg_variable)
isParameter = true;
}
const Value *Address = DI.getAddress();
if (!Address)
return 0;
if (const BitCastInst *BCI = dyn_cast<BitCastInst>(Address))
Address = BCI->getOperand(0);
const AllocaInst *AI = dyn_cast<AllocaInst>(Address);
// Don't handle byval struct arguments or VLAs, for example.
if (!AI)
return 0;
DenseMap<const AllocaInst*, int>::iterator SI =
FuncInfo.StaticAllocaMap.find(AI);
if (SI == FuncInfo.StaticAllocaMap.end())
return 0; // VLAs.
int FI = SI->second;
if (AI) {
// Don't handle byval arguments or VLAs, for example.
// Non-byval arguments are handled here (they refer to the stack temporary
// alloca at this point).
DenseMap<const AllocaInst*, int>::iterator SI =
FuncInfo.StaticAllocaMap.find(AI);
if (SI == FuncInfo.StaticAllocaMap.end())
return 0; // VLAs.
int FI = SI->second;
MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI();
if (!DI.getDebugLoc().isUnknown() && MMI.hasDebugInfo())
MMI.setVariableDbgInfo(Variable, FI, DI.getDebugLoc());
MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI();
if (!DI.getDebugLoc().isUnknown() && MMI.hasDebugInfo())
MMI.setVariableDbgInfo(Variable, FI, DI.getDebugLoc());
}
// Build an entry in DbgOrdering. Debug info input nodes get an SDNodeOrder
// but do not always have a corresponding SDNode built. The SDNodeOrder
// absolute, but not relative, values are different depending on whether
// debug info exists.
++SDNodeOrder;
SDValue &N = NodeMap[Address];
SDDbgValue *SDV;
if (N.getNode()) {
if (isParameter && !AI) {
FrameIndexSDNode *FINode = dyn_cast<FrameIndexSDNode>(N.getNode());
if (FINode)
// Byval parameter. We have a frame index at this point.
SDV = DAG.getDbgValue(Variable, FINode->getIndex(),
0, dl, SDNodeOrder);
else
// Can't do anything with other non-AI cases yet. This might be a
// parameter of a callee function that got inlined, for example.
return 0;
} else if (AI)
SDV = DAG.getDbgValue(Variable, N.getNode(), N.getResNo(),
0, dl, SDNodeOrder);
else
// Can't do anything with other non-AI cases yet.
return 0;
DAG.AddDbgValue(SDV, N.getNode(), isParameter);
} else {
// This isn't useful, but it shows what we're missing.
SDV = DAG.getDbgValue(Variable, UndefValue::get(Address->getType()),
0, dl, SDNodeOrder);
DAG.AddDbgValue(SDV, 0, isParameter);
}
return 0;
}
case Intrinsic::dbg_value: {
@ -3819,20 +3862,23 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
// absolute, but not relative, values are different depending on whether
// debug info exists.
++SDNodeOrder;
SDDbgValue *SDV;
if (isa<ConstantInt>(V) || isa<ConstantFP>(V)) {
DAG.AddDbgValue(DAG.getDbgValue(Variable, V, Offset, dl, SDNodeOrder));
SDV = DAG.getDbgValue(Variable, V, Offset, dl, SDNodeOrder);
DAG.AddDbgValue(SDV, 0, false);
} else {
SDValue &N = NodeMap[V];
if (N.getNode())
DAG.AddDbgValue(DAG.getDbgValue(Variable, N.getNode(),
N.getResNo(), Offset, dl, SDNodeOrder),
N.getNode());
else
if (N.getNode()) {
SDV = DAG.getDbgValue(Variable, N.getNode(),
N.getResNo(), Offset, dl, SDNodeOrder);
DAG.AddDbgValue(SDV, N.getNode(), false);
} else {
// We may expand this to cover more cases. One case where we have no
// data available is an unreferenced parameter; we need this fallback.
DAG.AddDbgValue(DAG.getDbgValue(Variable,
UndefValue::get(V->getType()),
Offset, dl, SDNodeOrder));
SDV = DAG.getDbgValue(Variable, UndefValue::get(V->getType()),
Offset, dl, SDNodeOrder);
DAG.AddDbgValue(SDV, 0, false);
}
}
// Build a debug info table entry.