diff --git a/include/llvm/Analysis/DebugInfo.h b/include/llvm/Analysis/DebugInfo.h index a8e124c6f09..6a0eb070c5b 100644 --- a/include/llvm/Analysis/DebugInfo.h +++ b/include/llvm/Analysis/DebugInfo.h @@ -15,6 +15,7 @@ #ifndef LLVM_ANALYSIS_DEBUGINFO_H #define LLVM_ANALYSIS_DEBUGINFO_H +#include "llvm/Target/TargetMachine.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Dwarf.h" @@ -70,6 +71,9 @@ namespace llvm { return getUnsignedField(0) & ~LLVMDebugVersionMask; } + /// ValidDebugInfo - Return true if V represents valid debug info value. + static bool ValidDebugInfo(Value *V, CodeGenOpt::Level OptLevel); + }; /// DIAnchor - A wrapper for various anchor descriptors. diff --git a/include/llvm/CodeGen/DwarfWriter.h b/include/llvm/CodeGen/DwarfWriter.h index 9ca7d7e4f2b..8e680e3e113 100644 --- a/include/llvm/CodeGen/DwarfWriter.h +++ b/include/llvm/CodeGen/DwarfWriter.h @@ -82,9 +82,6 @@ public: /// void EndFunction(MachineFunction *MF); - /// ValidDebugInfo - Return true if V represents valid debug info value. - bool ValidDebugInfo(Value *V, CodeGenOpt::Level OptLevel); - /// RecordSourceLine - Register a source line with debug info. Returns a /// unique label ID used to generate a label and provide correspondence to /// the source line list. diff --git a/lib/Analysis/DebugInfo.cpp b/lib/Analysis/DebugInfo.cpp index 7db9b2f3bc4..61e8a1086b3 100644 --- a/lib/Analysis/DebugInfo.cpp +++ b/lib/Analysis/DebugInfo.cpp @@ -20,13 +20,57 @@ #include "llvm/Instructions.h" #include "llvm/Module.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/Support/Dwarf.h" #include "llvm/Support/Streams.h" using namespace llvm; +using namespace llvm::dwarf; //===----------------------------------------------------------------------===// // DIDescriptor //===----------------------------------------------------------------------===// +/// ValidDebugInfo - Return true if V represents valid debug info value. +bool DIDescriptor::ValidDebugInfo(Value *V, CodeGenOpt::Level OptLevel) { + if (!V) + return false; + + GlobalVariable *GV = dyn_cast(V->stripPointerCasts()); + if (!GV) + return false; + + if (!GV->hasInternalLinkage () && !GV->hasLinkOnceLinkage()) + return false; + + DIDescriptor DI(GV); + + // Check current version. Allow Version6 for now. + unsigned Version = DI.getVersion(); + if (Version != LLVMDebugVersion && Version != LLVMDebugVersion6) + return false; + + unsigned Tag = DI.getTag(); + switch (Tag) { + case DW_TAG_variable: + assert(DIVariable(GV).Verify() && "Invalid DebugInfo value"); + break; + case DW_TAG_compile_unit: + assert(DICompileUnit(GV).Verify() && "Invalid DebugInfo value"); + break; + case DW_TAG_subprogram: + assert(DISubprogram(GV).Verify() && "Invalid DebugInfo value"); + break; + case DW_TAG_lexical_block: + /// FIXME. This interfers with the quality of generated code when + /// during optimization. + if (OptLevel != CodeGenOpt::None) + return false; + default: + break; + } + + return true; +} + DIDescriptor::DIDescriptor(GlobalVariable *gv, unsigned RequiredTag) { GV = gv; diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp index cb24d7d7007..848f45ea8c9 100644 --- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp @@ -69,28 +69,6 @@ static const unsigned InitValuesSetSize = 9; // log2(512) class DIE; class DIEValue; -//===----------------------------------------------------------------------===// -/// Utility routines. -/// -/// getGlobalVariable - Return either a direct or cast Global value. -/// -static GlobalVariable *getGlobalVariable(Value *V) { - if (GlobalVariable *GV = dyn_cast(V)) { - return GV; - } else if (ConstantExpr *CE = dyn_cast(V)) { - if (CE->getOpcode() == Instruction::BitCast) { - return dyn_cast(CE->getOperand(0)); - } else if (CE->getOpcode() == Instruction::GetElementPtr) { - for (unsigned int i=1; igetNumOperands(); i++) { - if (!CE->getOperand(i)->isNullValue()) - return NULL; - } - return dyn_cast(CE->getOperand(0)); - } - } - return NULL; -} - //===----------------------------------------------------------------------===// /// DWLabel - Labels are used to track locations in the assembler file. /// Labels appear in the form @verbatim @endverbatim, @@ -3349,61 +3327,6 @@ public: DebugTimer->stopTimer(); } - /// ValidDebugInfo - Return true if V represents valid debug info value. - bool ValidDebugInfo(Value *V, CodeGenOpt::Level OptLevel) { - if (!V) - return false; - - if (!shouldEmit) - return false; - - GlobalVariable *GV = getGlobalVariable(V); - if (!GV) - return false; - - if (!GV->hasInternalLinkage () && !GV->hasLinkOnceLinkage()) - return false; - - if (TimePassesIsEnabled) - DebugTimer->startTimer(); - - DIDescriptor DI(GV); - - // Check current version. Allow Version6 for now. - unsigned Version = DI.getVersion(); - if (Version != LLVMDebugVersion && Version != LLVMDebugVersion6) { - if (TimePassesIsEnabled) - DebugTimer->stopTimer(); - - return false; - } - - unsigned Tag = DI.getTag(); - switch (Tag) { - case DW_TAG_variable: - assert(DIVariable(GV).Verify() && "Invalid DebugInfo value"); - break; - case DW_TAG_compile_unit: - assert(DICompileUnit(GV).Verify() && "Invalid DebugInfo value"); - break; - case DW_TAG_subprogram: - assert(DISubprogram(GV).Verify() && "Invalid DebugInfo value"); - break; - case DW_TAG_lexical_block: - /// FIXME. This interfers with the qualitfy of generated code when - /// during optimization. - if (OptLevel != CodeGenOpt::None) - return false; - default: - break; - } - - if (TimePassesIsEnabled) - DebugTimer->stopTimer(); - - return true; - } - /// RecordSourceLine - Records location information and associates it with a /// label. Returns a unique label ID used to generate a label and provide /// correspondence to the source line list. @@ -4752,11 +4675,6 @@ void DwarfWriter::EndFunction(MachineFunction *MF) { MMI->EndFunction(); } -/// ValidDebugInfo - Return true if V represents valid debug info value. -bool DwarfWriter::ValidDebugInfo(Value *V, CodeGenOpt::Level OptLevel) { - return DD && DD->ValidDebugInfo(V, OptLevel); -} - /// RecordSourceLine - Records location information and associates it with a /// label. Returns a unique label ID used to generate a label and provide /// correspondence to the source line list. @@ -4790,7 +4708,7 @@ void DwarfWriter::RecordVariable(GlobalVariable *GV, unsigned FrameIndex, /// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should /// be emitted. bool DwarfWriter::ShouldEmitDwarfDebug() const { - return DD->ShouldEmitDwarfDebug(); + return DD && DD->ShouldEmitDwarfDebug(); } //// RecordInlinedFnStart - Global variable GV is inlined at the location marked diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index 58e84908820..afcda1f82e0 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -327,21 +327,24 @@ bool FastISel::SelectCall(User *I) { default: break; case Intrinsic::dbg_stoppoint: { DbgStopPointInst *SPI = cast(I); - if (DW && DW->ValidDebugInfo(SPI->getContext(), CodeGenOpt::None)) { + if (DIDescriptor::ValidDebugInfo(SPI->getContext(), CodeGenOpt::None)) { DICompileUnit CU(cast(SPI->getContext())); unsigned Line = SPI->getLine(); unsigned Col = SPI->getColumn(); - unsigned ID = DW->RecordSourceLine(Line, Col, CU); unsigned Idx = MF.getOrCreateDebugLocID(CU.getGV(), Line, Col); setCurDebugLoc(DebugLoc::get(Idx)); - const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL); - BuildMI(MBB, DL, II).addImm(ID); + if (DW && DW->ShouldEmitDwarfDebug()) { + unsigned ID = DW->RecordSourceLine(Line, Col, CU); + const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL); + BuildMI(MBB, DL, II).addImm(ID); + } } return true; } case Intrinsic::dbg_region_start: { DbgRegionStartInst *RSI = cast(I); - if (DW && DW->ValidDebugInfo(RSI->getContext(), CodeGenOpt::None)) { + if (DIDescriptor::ValidDebugInfo(RSI->getContext(), CodeGenOpt::None) && + DW && DW->ShouldEmitDwarfDebug()) { unsigned ID = DW->RecordRegionStart(cast(RSI->getContext())); const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL); @@ -351,7 +354,8 @@ bool FastISel::SelectCall(User *I) { } case Intrinsic::dbg_region_end: { DbgRegionEndInst *REI = cast(I); - if (DW && DW->ValidDebugInfo(REI->getContext(), CodeGenOpt::None)) { + if (DIDescriptor::ValidDebugInfo(REI->getContext(), CodeGenOpt::None) && + DW && DW->ShouldEmitDwarfDebug()) { unsigned ID = 0; DISubprogram Subprogram(cast(REI->getContext())); if (!Subprogram.isNull() && !Subprogram.describes(MF.getFunction())) { @@ -373,43 +377,46 @@ bool FastISel::SelectCall(User *I) { return true; } case Intrinsic::dbg_func_start: { - if (!DW) return true; DbgFuncStartInst *FSI = cast(I); Value *SP = FSI->getSubprogram(); + if (!DIDescriptor::ValidDebugInfo(SP, CodeGenOpt::None)) + return true; - if (DW->ValidDebugInfo(SP, CodeGenOpt::None)) { - // llvm.dbg.func.start implicitly defines a dbg_stoppoint which is what - // (most?) gdb expects. - DebugLoc PrevLoc = DL; - DISubprogram Subprogram(cast(SP)); - DICompileUnit CompileUnit = Subprogram.getCompileUnit(); + // llvm.dbg.func.start implicitly defines a dbg_stoppoint which is what + // (most?) gdb expects. + DebugLoc PrevLoc = DL; + DISubprogram Subprogram(cast(SP)); + DICompileUnit CompileUnit = Subprogram.getCompileUnit(); - if (!Subprogram.describes(MF.getFunction())) { - // This is a beginning of an inlined function. - - // If llvm.dbg.func.start is seen in a new block before any - // llvm.dbg.stoppoint intrinsic then the location info is unknown. - // FIXME : Why DebugLoc is reset at the beginning of each block ? - if (PrevLoc.isUnknown()) - return true; - // Record the source line. - unsigned Line = Subprogram.getLineNumber(); + if (!Subprogram.describes(MF.getFunction())) { + // This is a beginning of an inlined function. + + // If llvm.dbg.func.start is seen in a new block before any + // llvm.dbg.stoppoint intrinsic then the location info is unknown. + // FIXME : Why DebugLoc is reset at the beginning of each block ? + if (PrevLoc.isUnknown()) + return true; + // Record the source line. + unsigned Line = Subprogram.getLineNumber(); + setCurDebugLoc(DebugLoc::get(MF.getOrCreateDebugLocID( + CompileUnit.getGV(), Line, 0))); + + if (DW && DW->ShouldEmitDwarfDebug()) { unsigned LabelID = DW->RecordSourceLine(Line, 0, CompileUnit); - setCurDebugLoc(DebugLoc::get(MF.getOrCreateDebugLocID( - CompileUnit.getGV(), Line, 0))); - const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL); BuildMI(MBB, DL, II).addImm(LabelID); DebugLocTuple PrevLocTpl = MF.getDebugLocTuple(PrevLoc); - DW->RecordInlinedFnStart(FSI, Subprogram, LabelID, + DW->RecordInlinedFnStart(FSI, Subprogram, LabelID, DICompileUnit(PrevLocTpl.CompileUnit), PrevLocTpl.Line, PrevLocTpl.Col); - } else { - // Record the source line. - unsigned Line = Subprogram.getLineNumber(); - setCurDebugLoc(DebugLoc::get(MF.getOrCreateDebugLocID( - CompileUnit.getGV(), Line, 0))); + } + } else { + // Record the source line. + unsigned Line = Subprogram.getLineNumber(); + setCurDebugLoc(DebugLoc::get(MF.getOrCreateDebugLocID( + CompileUnit.getGV(), Line, 0))); + if (DW && DW->ShouldEmitDwarfDebug()) { DW->RecordSourceLine(Line, 0, CompileUnit); // llvm.dbg.func_start also defines beginning of function scope. DW->RecordRegionStart(cast(FSI->getSubprogram())); @@ -421,7 +428,8 @@ bool FastISel::SelectCall(User *I) { case Intrinsic::dbg_declare: { DbgDeclareInst *DI = cast(I); Value *Variable = DI->getVariable(); - if (DW && DW->ValidDebugInfo(Variable, CodeGenOpt::None)) { + if (DIDescriptor::ValidDebugInfo(Variable, CodeGenOpt::None) && + DW && DW->ShouldEmitDwarfDebug()) { // Determine the address of the declared object. Value *Address = DI->getAddress(); if (BitCastInst *BCI = dyn_cast(Address)) diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index aecfbb4c341..acdb04339bd 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -331,11 +331,10 @@ void FunctionLoweringInfo::set(Function &fn, MachineFunction &mf, switch (F->getIntrinsicID()) { default: break; case Intrinsic::dbg_stoppoint: { - DwarfWriter *DW = DAG.getDwarfWriter(); DbgStopPointInst *SPI = cast(I); - if (DW && DW->ValidDebugInfo(SPI->getContext(), - CodeGenOpt::Default)) { + if (DIDescriptor::ValidDebugInfo(SPI->getContext(), + CodeGenOpt::Default)) { DICompileUnit CU(cast(SPI->getContext())); unsigned idx = MF->getOrCreateDebugLocID(CU.getGV(), SPI->getLine(), @@ -346,18 +345,15 @@ void FunctionLoweringInfo::set(Function &fn, MachineFunction &mf, break; } case Intrinsic::dbg_func_start: { - DwarfWriter *DW = DAG.getDwarfWriter(); - if (DW) { - DbgFuncStartInst *FSI = cast(I); - Value *SP = FSI->getSubprogram(); + DbgFuncStartInst *FSI = cast(I); + Value *SP = FSI->getSubprogram(); - if (DW->ValidDebugInfo(SP, CodeGenOpt::Default)) { - DISubprogram Subprogram(cast(SP)); - DICompileUnit CU(Subprogram.getCompileUnit()); - unsigned Line = Subprogram.getLineNumber(); - DL = DebugLoc::get(MF->getOrCreateDebugLocID(CU.getGV(), - Line, 0)); - } + if (DIDescriptor::ValidDebugInfo(SP, CodeGenOpt::Default)) { + DISubprogram Subprogram(cast(SP)); + DICompileUnit CU(Subprogram.getCompileUnit()); + unsigned Line = Subprogram.getLineNumber(); + DL = DebugLoc::get(MF->getOrCreateDebugLocID(CU.getGV(), + Line, 0)); } break; @@ -3890,9 +3886,8 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { return 0; } case Intrinsic::dbg_stoppoint: { - DwarfWriter *DW = DAG.getDwarfWriter(); DbgStopPointInst &SPI = cast(I); - if (DW && DW->ValidDebugInfo(SPI.getContext(), OptLevel)) { + if (DIDescriptor::ValidDebugInfo(SPI.getContext(), OptLevel)) { MachineFunction &MF = DAG.getMachineFunction(); if (OptLevel == CodeGenOpt::None) DAG.setRoot(DAG.getDbgStopPoint(getRoot(), @@ -3910,7 +3905,8 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { DwarfWriter *DW = DAG.getDwarfWriter(); DbgRegionStartInst &RSI = cast(I); - if (DW && DW->ValidDebugInfo(RSI.getContext(), OptLevel)) { + if (DIDescriptor::ValidDebugInfo(RSI.getContext(), OptLevel) && + DW && DW->ShouldEmitDwarfDebug()) { unsigned LabelID = DW->RecordRegionStart(cast(RSI.getContext())); DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(), @@ -3923,7 +3919,8 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { DwarfWriter *DW = DAG.getDwarfWriter(); DbgRegionEndInst &REI = cast(I); - if (DW && DW->ValidDebugInfo(REI.getContext(), OptLevel)) { + if (DIDescriptor::ValidDebugInfo(REI.getContext(), OptLevel) && + DW && DW->ShouldEmitDwarfDebug()) { MachineFunction &MF = DAG.getMachineFunction(); DISubprogram Subprogram(cast(REI.getContext())); std::string SPName; @@ -3955,84 +3952,87 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { } case Intrinsic::dbg_func_start: { DwarfWriter *DW = DAG.getDwarfWriter(); - if (!DW) return 0; DbgFuncStartInst &FSI = cast(I); Value *SP = FSI.getSubprogram(); - if (SP && DW->ValidDebugInfo(SP, OptLevel)) { - MachineFunction &MF = DAG.getMachineFunction(); - if (OptLevel == CodeGenOpt::None) { - // llvm.dbg.func.start implicitly defines a dbg_stoppoint which is what - // (most?) gdb expects. - DebugLoc PrevLoc = CurDebugLoc; - DISubprogram Subprogram(cast(SP)); - DICompileUnit CompileUnit = Subprogram.getCompileUnit(); - - if (!Subprogram.describes(MF.getFunction())) { - // This is a beginning of an inlined function. + if (!DIDescriptor::ValidDebugInfo(SP, OptLevel)) + return 0; - // If llvm.dbg.func.start is seen in a new block before any - // llvm.dbg.stoppoint intrinsic then the location info is unknown. - // FIXME : Why DebugLoc is reset at the beginning of each block ? - if (PrevLoc.isUnknown()) - return 0; + MachineFunction &MF = DAG.getMachineFunction(); + if (OptLevel == CodeGenOpt::None) { + // llvm.dbg.func.start implicitly defines a dbg_stoppoint which is what + // (most?) gdb expects. + DebugLoc PrevLoc = CurDebugLoc; + DISubprogram Subprogram(cast(SP)); + DICompileUnit CompileUnit = Subprogram.getCompileUnit(); - // Record the source line. - unsigned Line = Subprogram.getLineNumber(); + if (!Subprogram.describes(MF.getFunction())) { + // This is a beginning of an inlined function. + + // If llvm.dbg.func.start is seen in a new block before any + // llvm.dbg.stoppoint intrinsic then the location info is unknown. + // FIXME : Why DebugLoc is reset at the beginning of each block ? + if (PrevLoc.isUnknown()) + return 0; + + // Record the source line. + unsigned Line = Subprogram.getLineNumber(); + setCurDebugLoc(DebugLoc::get( + MF.getOrCreateDebugLocID(CompileUnit.getGV(), Line, 0))); + + if (DW && DW->ShouldEmitDwarfDebug()) { unsigned LabelID = DW->RecordSourceLine(Line, 0, CompileUnit); - setCurDebugLoc(DebugLoc::get( - MF.getOrCreateDebugLocID(CompileUnit.getGV(), Line, 0))); - DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(), getRoot(), LabelID)); DebugLocTuple PrevLocTpl = MF.getDebugLocTuple(PrevLoc); - DW->RecordInlinedFnStart(&FSI, Subprogram, LabelID, + DW->RecordInlinedFnStart(&FSI, Subprogram, LabelID, DICompileUnit(PrevLocTpl.CompileUnit), PrevLocTpl.Line, PrevLocTpl.Col); - } else { - // Record the source line. - unsigned Line = Subprogram.getLineNumber(); - setCurDebugLoc(DebugLoc::get( - MF.getOrCreateDebugLocID(CompileUnit.getGV(), Line, 0))); + } + } else { + // Record the source line. + unsigned Line = Subprogram.getLineNumber(); + setCurDebugLoc(DebugLoc::get( + MF.getOrCreateDebugLocID(CompileUnit.getGV(), Line, 0))); + if (DW && DW->ShouldEmitDwarfDebug()) { DW->RecordSourceLine(Line, 0, CompileUnit); // llvm.dbg.func_start also defines beginning of function scope. DW->RecordRegionStart(cast(FSI.getSubprogram())); } - } else { - DISubprogram Subprogram(cast(SP)); - - std::string SPName; - Subprogram.getLinkageName(SPName); - if (!SPName.empty() - && strcmp(SPName.c_str(), MF.getFunction()->getNameStart())) { - // This is beginning of inlined function. Debugging information for - // inlined function is not handled yet (only supported by FastISel). - return 0; - } - - // llvm.dbg.func.start implicitly defines a dbg_stoppoint which is - // what (most?) gdb expects. - DICompileUnit CompileUnit = Subprogram.getCompileUnit(); - - // Record the source line but does not create a label for the normal - // function start. It will be emitted at asm emission time. However, - // create a label if this is a beginning of inlined function. - unsigned Line = Subprogram.getLineNumber(); - setCurDebugLoc(DebugLoc::get( - MF.getOrCreateDebugLocID(CompileUnit.getGV(), Line, 0))); - // FIXME - Start new region because llvm.dbg.func_start also defines - // beginning of function scope. } + } else { + DISubprogram Subprogram(cast(SP)); + + std::string SPName; + Subprogram.getLinkageName(SPName); + if (!SPName.empty() + && strcmp(SPName.c_str(), MF.getFunction()->getNameStart())) { + // This is beginning of inlined function. Debugging information for + // inlined function is not handled yet (only supported by FastISel). + return 0; + } + + // llvm.dbg.func.start implicitly defines a dbg_stoppoint which is + // what (most?) gdb expects. + DICompileUnit CompileUnit = Subprogram.getCompileUnit(); + + // Record the source line but does not create a label for the normal + // function start. It will be emitted at asm emission time. However, + // create a label if this is a beginning of inlined function. + unsigned Line = Subprogram.getLineNumber(); + setCurDebugLoc(DebugLoc::get( + MF.getOrCreateDebugLocID(CompileUnit.getGV(), Line, 0))); + // FIXME - Start new region because llvm.dbg.func_start also defines + // beginning of function scope. } return 0; } case Intrinsic::dbg_declare: { if (OptLevel == CodeGenOpt::None) { - DwarfWriter *DW = DAG.getDwarfWriter(); DbgDeclareInst &DI = cast(I); Value *Variable = DI.getVariable(); - if (DW && DW->ValidDebugInfo(Variable, OptLevel)) + if (DIDescriptor::ValidDebugInfo(Variable, OptLevel)) DAG.setRoot(DAG.getNode(ISD::DECLARE, dl, MVT::Other, getRoot(), getValue(DI.getAddress()), getValue(Variable))); } else {