llvm.org GIT mirror llvm / 32360a7
Add line numbers to OProfile. To do this, I added a processDebugLoc() call to the MachineCodeEmitter interface and made copying the start line of a function not conditional on whether we're emitting Dwarf debug information. I'll propagate the processDebugLoc() calls to the non-X86 targets in a followup patch. In the long run, it'll probably be better to gather this information through the DwarfWriter, but the DwarfWriter currently depends on the AsmPrinter and TargetAsmInfo, and fixing that would be out of the way for this patch. There's a bug in OProfile 0.9.4 that makes it ignore line numbers for addresses above 4G, and a patch fixing it at http://thread.gmane.org/gmane.linux.oprofile/7634 Sample output: $ sudo opcontrol --reset; sudo opcontrol --start-daemon; sudo opcontrol --start; `pwd`/Debug/bin/lli fib.bc; sudo opcontrol --stop Signalling daemon... done Profiler running. fib(40) == 165580141 Stopping profiling. $ opreport -g -d -l `pwd`/Debug/bin/lli|head -60 Overflow stats not available CPU: Core 2, speed 1998 MHz (estimated) Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 100000 vma samples % linenr info image name symbol name 00007f67a30370b0 25489 61.2554 fib.c:24 10946.jo fib_left 00007f67a30370b0 1634 6.4106 fib.c:24 00007f67a30370b1 83 0.3256 fib.c:24 00007f67a30370b9 1997 7.8348 fib.c:24 00007f67a30370c6 2080 8.1604 fib.c:27 00007f67a30370c8 988 3.8762 fib.c:27 00007f67a30370cd 1315 5.1591 fib.c:27 00007f67a30370cf 251 0.9847 fib.c:27 00007f67a30370d3 1191 4.6726 fib.c:27 00007f67a30370d6 975 3.8252 fib.c:27 00007f67a30370db 1010 3.9625 fib.c:27 00007f67a30370dd 242 0.9494 fib.c:27 00007f67a30370e1 2782 10.9145 fib.c:28 00007f67a30370e5 3768 14.7828 fib.c:28 00007f67a30370eb 615 2.4128 (no location information) 00007f67a30370f3 6558 25.7287 (no location information) 00007f67a3037100 15603 37.4973 fib.c:29 10946.jo fib_right 00007f67a3037100 1646 10.5493 fib.c:29 00007f67a3037101 45 0.2884 fib.c:29 00007f67a3037109 2372 15.2022 fib.c:29 00007f67a3037116 2234 14.3178 fib.c:32 00007f67a3037118 612 3.9223 fib.c:32 00007f67a303711d 622 3.9864 fib.c:32 00007f67a303711f 385 2.4675 fib.c:32 00007f67a3037123 404 2.5892 fib.c:32 00007f67a3037126 634 4.0633 fib.c:32 00007f67a303712b 870 5.5759 fib.c:32 00007f67a303712d 62 0.3974 fib.c:32 00007f67a3037131 1848 11.8439 fib.c:33 00007f67a3037135 2840 18.2016 fib.c:33 00007f67a303713a 1 0.0064 fib.c:33 00007f67a303713b 1023 6.5564 (no location information) 00007f67a3037143 5 0.0320 (no location information) 000000000080c1e4 15 0.0360 MachineOperand.h:150 lli llvm::MachineOperand::isReg() const 000000000080c1e4 6 40.0000 MachineOperand.h:150 000000000080c1ec 2 13.3333 MachineOperand.h:150 ... git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@76102 91177308-0d34-0410-b5e6-96231b3b80d8 Jeffrey Yasskin 11 years ago
7 changed file(s) with 131 addition(s) and 9 deletion(s). Raw diff Collapse all Expand all
1717 #define LLVM_CODEGEN_MACHINECODEEMITTER_H
1818
1919 #include "llvm/Support/DataTypes.h"
20 #include "llvm/Support/DebugLoc.h"
2021
2122 namespace llvm {
2223
231232 (*(uint64_t*)Addr) = (uint64_t)Value;
232233 }
233234
234
235 /// processDebugLoc - Records debug location information about a
236 /// MachineInstruction. This is called before emitting any bytes associated
237 /// with the instruction. Even if successive instructions have the same debug
238 /// location, this method will be called for each one.
239 virtual void processDebugLoc(DebugLoc DL) {}
240
235241 /// emitLabel - Emits a label
236242 virtual void emitLabel(uint64_t LabelID) = 0;
237243
1515 #define LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H
1616
1717 #include "llvm/Support/DataTypes.h"
18 #include "llvm/Support/DebugLoc.h"
19
20 #include
1821
1922 namespace llvm {
2023 class Function;
24 class MachineFunction;
2125
2226 /// Empty for now, but this object will contain all details about the
2327 /// generated machine code that a Listener might care about.
2428 struct JITEvent_EmittedFunctionDetails {
29 const MachineFunction *MF;
30
31 struct LineStart {
32 // The address at which the current line changes.
33 uintptr_t Address;
34 // The new location information. These can be translated to
35 // DebugLocTuples using MF->getDebugLocTuple().
36 DebugLoc Loc;
37 };
38 // This holds line boundary information sorted by address.
39 std::vector LineStarts;
2540 };
2641
2742 /// JITEventListener - This interface is used by the JIT to notify clients about
2525 struct DebugLocTuple {
2626 GlobalVariable *CompileUnit;
2727 unsigned Line, Col;
28
29 DebugLocTuple()
30 : CompileUnit(0), Line(~0U), Col(~0U) {};
2831
2932 DebugLocTuple(GlobalVariable *v, unsigned l, unsigned c)
3033 : CompileUnit(v), Line(l), Col(c) {};
39173917 case Intrinsic::dbg_func_start: {
39183918 DwarfWriter *DW = DAG.getDwarfWriter();
39193919 DbgFuncStartInst &FSI = cast(I);
3920 if (!isValidDebugInfoIntrinsic(FSI, CodeGenOpt::None) || !DW
3921 || !DW->ShouldEmitDwarfDebug())
3920 if (!isValidDebugInfoIntrinsic(FSI, CodeGenOpt::None))
39223921 return 0;
39233922
39243923 MachineFunction &MF = DAG.getMachineFunction();
39393938 // Record the source line.
39403939 setCurDebugLoc(ExtractDebugLocation(FSI, MF.getDebugLocInfo()));
39413940
3941 if (!DW || !DW->ShouldEmitDwarfDebug())
3942 return 0;
39423943 DebugLocTuple PrevLocTpl = MF.getDebugLocTuple(PrevLoc);
39433944 DISubprogram SP(cast(FSI.getSubprogram()));
39443945 DICompileUnit CU(PrevLocTpl.CompileUnit);
39523953
39533954 // This is a beginning of a new function.
39543955 MF.setDefaultDebugLoc(ExtractDebugLocation(FSI, MF.getDebugLocInfo()));
3955
3956
3957 if (!DW || !DW->ShouldEmitDwarfDebug())
3958 return 0;
39563959 // llvm.dbg.func_start also defines beginning of function scope.
39573960 DW->RecordRegionStart(cast(FSI.getSubprogram()));
39583961 return 0;
472472 // CurFn - The llvm function being emitted. Only valid during
473473 // finishFunction().
474474 const Function *CurFn;
475
475
476 /// Information about emitted code, which is passed to the
477 /// JITEventListeners. This is reset in startFunction and used in
478 /// finishFunction.
479 JITEvent_EmittedFunctionDetails EmissionDetails;
480
476481 // CurFnStubUses - For a given Function, a vector of stubs that it
477482 // references. This facilitates the JIT detecting that a stub is no
478483 // longer used, so that it may be deallocated.
486491 // ExtFnStubs - A map of external function names to stubs which have entries
487492 // in the JITResolver's ExternalFnToStubMap.
488493 StringMap ExtFnStubs;
494
495 DebugLocTuple PrevDLT;
489496
490497 public:
491498 JITEmitter(JIT &jit, JITMemoryManager *JMM) : Resolver(jit), CurFn(0) {
566573 /// MachineRelocations that reference external functions by name.
567574 const StringMap &getExternalFnStubs() const { return ExtFnStubs; }
568575
576 virtual void processDebugLoc(DebugLoc DL);
577
569578 virtual void emitLabel(uint64_t LabelID) {
570579 if (LabelLocations.size() <= LabelID)
571580 LabelLocations.resize((LabelID+1)*2);
673682
674683 SmallPtrSet &FnRefs = StubFnRefs[StubAddr];
675684 FnRefs.insert(CurFn);
685 }
686
687 void JITEmitter::processDebugLoc(DebugLoc DL) {
688 if (!DL.isUnknown()) {
689 DebugLocTuple CurDLT = EmissionDetails.MF->getDebugLocTuple(DL);
690
691 if (CurDLT.CompileUnit != 0 && PrevDLT != CurDLT) {
692 JITEvent_EmittedFunctionDetails::LineStart NextLine;
693 NextLine.Address = getCurrentPCValue();
694 NextLine.Loc = DL;
695 EmissionDetails.LineStarts.push_back(NextLine);
696 }
697
698 PrevDLT = CurDLT;
699 }
676700 }
677701
678702 static unsigned GetConstantPoolSizeInBytes(MachineConstantPool *MCP,
917941 TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr);
918942
919943 MBBLocations.clear();
944
945 EmissionDetails.MF = &F;
946 EmissionDetails.LineStarts.clear();
920947 }
921948
922949 bool JITEmitter::finishFunction(MachineFunction &F) {
10271054 // Invalidate the icache if necessary.
10281055 sys::Memory::InvalidateInstructionCache(FnStart, FnEnd-FnStart);
10291056
1030 JITEvent_EmittedFunctionDetails Details;
10311057 TheJIT->NotifyFunctionEmitted(*F.getFunction(), FnStart, FnEnd-FnStart,
1032 Details);
1058 EmissionDetails);
10331059
10341060 DOUT << "JIT: Finished CodeGen of [" << (void*)FnStart
10351061 << "] Function: " << F.getFunction()->getName()
1717
1818 #define DEBUG_TYPE "oprofile-jit-event-listener"
1919 #include "llvm/Function.h"
20 #include "llvm/Analysis/DebugInfo.h"
21 #include "llvm/CodeGen/MachineFunction.h"
2022 #include "llvm/ExecutionEngine/JITEventListener.h"
2123 #include "llvm/Support/Debug.h"
2224 #include "llvm/System/Errno.h"
6365 }
6466 }
6567
68 class FilenameCache {
69 // Holds the filename of each CompileUnit, so that we can pass the
70 // pointer into oprofile. These char*s are freed in the destructor.
71 DenseMap Filenames;
72 // Used as the scratch space in DICompileUnit::getFilename().
73 std::string TempFilename;
74
75 public:
76 const char* getFilename(GlobalVariable *CompileUnit) {
77 char *&Filename = Filenames[CompileUnit];
78 if (Filename == NULL) {
79 DICompileUnit CU(CompileUnit);
80 Filename = strdup(CU.getFilename(TempFilename).c_str());
81 }
82 return Filename;
83 }
84 ~FilenameCache() {
85 for (DenseMap::iterator
86 I = Filenames.begin(), E = Filenames.end(); I != E;++I) {
87 free(I->second);
88 }
89 }
90 };
91
92 static debug_line_info LineStartToOProfileFormat(
93 const MachineFunction &MF, FilenameCache &Filenames,
94 uintptr_t Address, DebugLoc Loc) {
95 debug_line_info Result;
96 Result.vma = Address;
97 const DebugLocTuple& tuple = MF.getDebugLocTuple(Loc);
98 Result.lineno = tuple.Line;
99 Result.filename = Filenames.getFilename(tuple.CompileUnit);
100 DOUT << "Mapping " << reinterpret_cast(Result.vma) << " to "
101 << Result.filename << ":" << Result.lineno << "\n";
102 return Result;
103 }
104
66105 // Adds the just-emitted function to the symbol table.
67106 void OProfileJITEventListener::NotifyFunctionEmitted(
68107 const Function &F, void *FnStart, size_t FnSize,
69 const EmittedFunctionDetails &) {
108 const EmittedFunctionDetails &Details) {
70109 const char *const FnName = F.getNameStart();
71110 assert(FnName != 0 && FnStart != 0 && "Bad symbol to add");
72111 if (op_write_native_code(Agent, FnName,
74113 FnStart, FnSize) == -1) {
75114 DOUT << "Failed to tell OProfile about native function " << FnName
76115 << " at [" << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n";
116 return;
117 }
118
119 // Now we convert the line number information from the address/DebugLoc format
120 // in Details to the address/filename/lineno format that OProfile expects.
121 // OProfile 0.9.4 (and maybe later versions) has a bug that causes it to
122 // ignore line numbers for addresses above 4G.
123 FilenameCache Filenames;
124 std::vector LineInfo;
125 LineInfo.reserve(1 + Details.LineStarts.size());
126 if (!Details.MF->getDefaultDebugLoc().isUnknown()) {
127 LineInfo.push_back(LineStartToOProfileFormat(
128 *Details.MF, Filenames,
129 reinterpret_cast(FnStart),
130 Details.MF->getDefaultDebugLoc()));
131 }
132 for (std::vector::const_iterator
133 I = Details.LineStarts.begin(), E = Details.LineStarts.end();
134 I != E; ++I) {
135 LineInfo.push_back(LineStartToOProfileFormat(
136 *Details.MF, Filenames, I->Address, I->Loc));
137 }
138 if (!LineInfo.empty()) {
139 if (op_write_debug_line_info(Agent, FnStart,
140 LineInfo.size(), &*LineInfo.begin()) == -1) {
141 DOUT << "Failed to tell OProfile about line numbers for native function "
142 << FnName << " at [" << FnStart << "-" << ((char*)FnStart + FnSize)
143 << "]\n";
144 }
77145 }
78146 }
79147
463463 const MachineInstr &MI,
464464 const TargetInstrDesc *Desc) {
465465 DOUT << MI;
466
467 MCE.processDebugLoc(MI.getDebugLoc());
466468
467469 unsigned Opcode = Desc->Opcode;
468470
815817 llvm_unreachable(0);
816818 }
817819 }
818