summaryrefslogtreecommitdiffstats
path: root/llvm/lib/ExecutionEngine
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/ExecutionEngine')
-rw-r--r--llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp32
-rw-r--r--llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp70
2 files changed, 98 insertions, 4 deletions
diff --git a/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp b/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp
index 63ac6f1c722..1cc16af4f68 100644
--- a/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp
+++ b/llvm/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/llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp b/llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp
index 6263a5b500d..888d83e0f29 100644
--- a/llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp
+++ b/llvm/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";
+ }
}
}
OpenPOWER on IntegriCloud