diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp | 9 | ||||
-rw-r--r-- | lib/ExecutionEngine/JIT/JITEmitter.cpp | 32 | ||||
-rw-r--r-- | lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp | 70 | ||||
-rw-r--r-- | lib/Target/X86/X86CodeEmitter.cpp | 3 |
4 files changed, 106 insertions, 8 deletions
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index 3c85118cad..05622f2d6c 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -3918,8 +3918,7 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { case Intrinsic::dbg_func_start: { DwarfWriter *DW = DAG.getDwarfWriter(); DbgFuncStartInst &FSI = cast<DbgFuncStartInst>(I); - if (!isValidDebugInfoIntrinsic(FSI, CodeGenOpt::None) || !DW - || !DW->ShouldEmitDwarfDebug()) + if (!isValidDebugInfoIntrinsic(FSI, CodeGenOpt::None)) return 0; MachineFunction &MF = DAG.getMachineFunction(); @@ -3940,6 +3939,8 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { // Record the source line. setCurDebugLoc(ExtractDebugLocation(FSI, MF.getDebugLocInfo())); + if (!DW || !DW->ShouldEmitDwarfDebug()) + return 0; DebugLocTuple PrevLocTpl = MF.getDebugLocTuple(PrevLoc); DISubprogram SP(cast<GlobalVariable>(FSI.getSubprogram())); DICompileUnit CU(PrevLocTpl.CompileUnit); @@ -3953,7 +3954,9 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { // This is a beginning of a new function. MF.setDefaultDebugLoc(ExtractDebugLocation(FSI, MF.getDebugLocInfo())); - + + if (!DW || !DW->ShouldEmitDwarfDebug()) + return 0; // llvm.dbg.func_start also defines beginning of function scope. DW->RecordRegionStart(cast<GlobalVariable>(FSI.getSubprogram())); return 0; diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp index 63ac6f1c72..1cc16af4f6 100644 --- a/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -473,7 +473,12 @@ namespace { // CurFn - The llvm function being emitted. Only valid during // finishFunction(). const Function *CurFn; - + + /// Information about emitted code, which is passed to the + /// JITEventListeners. This is reset in startFunction and used in + /// finishFunction. + JITEvent_EmittedFunctionDetails EmissionDetails; + // CurFnStubUses - For a given Function, a vector of stubs that it // references. This facilitates the JIT detecting that a stub is no // longer used, so that it may be deallocated. @@ -488,6 +493,8 @@ namespace { // in the JITResolver's ExternalFnToStubMap. StringMap<void *> ExtFnStubs; + DebugLocTuple PrevDLT; + public: JITEmitter(JIT &jit, JITMemoryManager *JMM) : Resolver(jit), CurFn(0) { MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager(); @@ -567,6 +574,8 @@ namespace { /// MachineRelocations that reference external functions by name. const StringMap<void*> &getExternalFnStubs() const { return ExtFnStubs; } + virtual void processDebugLoc(DebugLoc DL); + virtual void emitLabel(uint64_t LabelID) { if (LabelLocations.size() <= LabelID) LabelLocations.resize((LabelID+1)*2); @@ -676,6 +685,21 @@ void JITEmitter::AddStubToCurrentFunction(void *StubAddr) { FnRefs.insert(CurFn); } +void JITEmitter::processDebugLoc(DebugLoc DL) { + if (!DL.isUnknown()) { + DebugLocTuple CurDLT = EmissionDetails.MF->getDebugLocTuple(DL); + + if (CurDLT.CompileUnit != 0 && PrevDLT != CurDLT) { + JITEvent_EmittedFunctionDetails::LineStart NextLine; + NextLine.Address = getCurrentPCValue(); + NextLine.Loc = DL; + EmissionDetails.LineStarts.push_back(NextLine); + } + + PrevDLT = CurDLT; + } +} + static unsigned GetConstantPoolSizeInBytes(MachineConstantPool *MCP, const TargetData *TD) { const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants(); @@ -918,6 +942,9 @@ void JITEmitter::startFunction(MachineFunction &F) { TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr); MBBLocations.clear(); + + EmissionDetails.MF = &F; + EmissionDetails.LineStarts.clear(); } bool JITEmitter::finishFunction(MachineFunction &F) { @@ -1028,9 +1055,8 @@ bool JITEmitter::finishFunction(MachineFunction &F) { // Invalidate the icache if necessary. sys::Memory::InvalidateInstructionCache(FnStart, FnEnd-FnStart); - JITEvent_EmittedFunctionDetails Details; TheJIT->NotifyFunctionEmitted(*F.getFunction(), FnStart, FnEnd-FnStart, - Details); + EmissionDetails); DOUT << "JIT: Finished CodeGen of [" << (void*)FnStart << "] Function: " << F.getFunction()->getName() diff --git a/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp b/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp index 6263a5b500..888d83e0f2 100644 --- a/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp +++ b/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp @@ -18,6 +18,8 @@ #define DEBUG_TYPE "oprofile-jit-event-listener" #include "llvm/Function.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/Support/Debug.h" #include "llvm/System/Errno.h" @@ -64,10 +66,47 @@ OProfileJITEventListener::~OProfileJITEventListener() { } } +class FilenameCache { + // Holds the filename of each CompileUnit, so that we can pass the + // pointer into oprofile. These char*s are freed in the destructor. + DenseMap<GlobalVariable*, char*> Filenames; + // Used as the scratch space in DICompileUnit::getFilename(). + std::string TempFilename; + + public: + const char* getFilename(GlobalVariable *CompileUnit) { + char *&Filename = Filenames[CompileUnit]; + if (Filename == NULL) { + DICompileUnit CU(CompileUnit); + Filename = strdup(CU.getFilename(TempFilename).c_str()); + } + return Filename; + } + ~FilenameCache() { + for (DenseMap<GlobalVariable*, char*>::iterator + I = Filenames.begin(), E = Filenames.end(); I != E;++I) { + free(I->second); + } + } +}; + +static debug_line_info LineStartToOProfileFormat( + const MachineFunction &MF, FilenameCache &Filenames, + uintptr_t Address, DebugLoc Loc) { + debug_line_info Result; + Result.vma = Address; + const DebugLocTuple& tuple = MF.getDebugLocTuple(Loc); + Result.lineno = tuple.Line; + Result.filename = Filenames.getFilename(tuple.CompileUnit); + DOUT << "Mapping " << reinterpret_cast<void*>(Result.vma) << " to " + << Result.filename << ":" << Result.lineno << "\n"; + return Result; +} + // Adds the just-emitted function to the symbol table. void OProfileJITEventListener::NotifyFunctionEmitted( const Function &F, void *FnStart, size_t FnSize, - const EmittedFunctionDetails &) { + const EmittedFunctionDetails &Details) { const char *const FnName = F.getNameStart(); assert(FnName != 0 && FnStart != 0 && "Bad symbol to add"); if (op_write_native_code(Agent, FnName, @@ -75,6 +114,35 @@ void OProfileJITEventListener::NotifyFunctionEmitted( FnStart, FnSize) == -1) { DOUT << "Failed to tell OProfile about native function " << FnName << " at [" << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n"; + return; + } + + // Now we convert the line number information from the address/DebugLoc format + // in Details to the address/filename/lineno format that OProfile expects. + // OProfile 0.9.4 (and maybe later versions) has a bug that causes it to + // ignore line numbers for addresses above 4G. + FilenameCache Filenames; + std::vector<debug_line_info> LineInfo; + LineInfo.reserve(1 + Details.LineStarts.size()); + if (!Details.MF->getDefaultDebugLoc().isUnknown()) { + LineInfo.push_back(LineStartToOProfileFormat( + *Details.MF, Filenames, + reinterpret_cast<uintptr_t>(FnStart), + Details.MF->getDefaultDebugLoc())); + } + for (std::vector<EmittedFunctionDetails::LineStart>::const_iterator + I = Details.LineStarts.begin(), E = Details.LineStarts.end(); + I != E; ++I) { + LineInfo.push_back(LineStartToOProfileFormat( + *Details.MF, Filenames, I->Address, I->Loc)); + } + if (!LineInfo.empty()) { + if (op_write_debug_line_info(Agent, FnStart, + LineInfo.size(), &*LineInfo.begin()) == -1) { + DOUT << "Failed to tell OProfile about line numbers for native function " + << FnName << " at [" << FnStart << "-" << ((char*)FnStart + FnSize) + << "]\n"; + } } } diff --git a/lib/Target/X86/X86CodeEmitter.cpp b/lib/Target/X86/X86CodeEmitter.cpp index 0831449841..825c51cf43 100644 --- a/lib/Target/X86/X86CodeEmitter.cpp +++ b/lib/Target/X86/X86CodeEmitter.cpp @@ -465,6 +465,8 @@ void Emitter<CodeEmitter>::emitInstruction( const TargetInstrDesc *Desc) { DOUT << MI; + MCE.processDebugLoc(MI.getDebugLoc()); + unsigned Opcode = Desc->Opcode; // Emit the lock opcode prefix as needed. @@ -816,4 +818,3 @@ void Emitter<CodeEmitter>::emitInstruction( llvm_unreachable(0); } } - |