X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=lib%2FExecutionEngine%2FIntelJITEvents%2FIntelJITEventListener.cpp;h=a131763193c0e6557c998730acd101e4a050de6c;hb=5b685b0cf84190af5bbe5363c734cecee3a92bde;hp=2ca4e3e41143de38b86a1555824d5439fa375c51;hpb=f4ccd110750a3f3fe6a107d5c74c649c2a0dc407;p=oota-llvm.git diff --git a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp index 2ca4e3e4114..a131763193c 100644 --- a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp +++ b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp @@ -13,26 +13,26 @@ //===----------------------------------------------------------------------===// #include "llvm/Config/config.h" +#include "IntelJITEventsWrapper.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/ExecutionEngine/JITEventListener.h" - -#define DEBUG_TYPE "amplifier-jit-event-listener" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/Metadata.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/DebugInfo/DIContext.h" -#include "llvm/ExecutionEngine/ObjectImage.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Object/SymbolSize.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Errno.h" -#include "llvm/IR/ValueHandle.h" -#include "EventListenerCommon.h" -#include "IntelJITEventsWrapper.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; -using namespace llvm::jitprofiling; +using namespace llvm::object; + +#define DEBUG_TYPE "amplifier-jit-event-listener" namespace { @@ -41,12 +41,12 @@ class IntelJITEventListener : public JITEventListener { std::unique_ptr Wrapper; MethodIDMap MethodIDs; - FilenameCache Filenames; typedef SmallVector MethodAddressVector; typedef DenseMap ObjectMap; ObjectMap LoadedObjectMap; + std::map> DebugObjects; public: IntelJITEventListener(IntelJITEventsWrapper* libraryWrapper) { @@ -56,36 +56,19 @@ public: ~IntelJITEventListener() { } - virtual void NotifyFunctionEmitted(const Function &F, - void *FnStart, size_t FnSize, - const EmittedFunctionDetails &Details); - - virtual void NotifyFreeingMachineCode(void *OldPtr); + void NotifyObjectEmitted(const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) override; - virtual void NotifyObjectEmitted(const ObjectImage &Obj); - - virtual void NotifyFreeingObject(const ObjectImage &Obj); + void NotifyFreeingObject(const ObjectFile &Obj) override; }; -static LineNumberInfo LineStartToIntelJITFormat( - uintptr_t StartAddress, - uintptr_t Address, - DebugLoc Loc) { - LineNumberInfo Result; - - Result.Offset = Address - StartAddress; - Result.LineNumber = Loc.getLine(); - - return Result; -} - static LineNumberInfo DILineInfoToIntelJITFormat(uintptr_t StartAddress, uintptr_t Address, DILineInfo Line) { LineNumberInfo Result; Result.Offset = Address - StartAddress; - Result.LineNumber = Line.getLine(); + Result.LineNumber = Line.Line; return Result; } @@ -112,153 +95,95 @@ static iJIT_Method_Load FunctionDescToIntelJITFormat( return Result; } -// Adds the just-emitted function to the symbol table. -void IntelJITEventListener::NotifyFunctionEmitted( - const Function &F, void *FnStart, size_t FnSize, - const EmittedFunctionDetails &Details) { - iJIT_Method_Load FunctionMessage = FunctionDescToIntelJITFormat(*Wrapper, - F.getName().data(), - reinterpret_cast(FnStart), - FnSize); - - std::vector LineInfo; - - if (!Details.LineStarts.empty()) { - // Now convert the line number information from the address/DebugLoc - // format in Details to the offset/lineno in Intel JIT API format. - - LineInfo.reserve(Details.LineStarts.size() + 1); - - DebugLoc FirstLoc = Details.LineStarts[0].Loc; - assert(!FirstLoc.isUnknown() - && "LineStarts should not contain unknown DebugLocs"); - - MDNode *FirstLocScope = FirstLoc.getScope(F.getContext()); - DISubprogram FunctionDI = getDISubprogram(FirstLocScope); - if (FunctionDI.Verify()) { - FunctionMessage.source_file_name = const_cast( - Filenames.getFullPath(FirstLocScope)); - - LineNumberInfo FirstLine; - FirstLine.Offset = 0; - FirstLine.LineNumber = FunctionDI.getLineNumber(); - LineInfo.push_back(FirstLine); - } +void IntelJITEventListener::NotifyObjectEmitted( + const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) { - for (std::vector::const_iterator I = - Details.LineStarts.begin(), E = Details.LineStarts.end(); - I != E; ++I) { - // This implementation ignores the DebugLoc filename because the Intel - // JIT API does not support multiple source files associated with a single - // JIT function - LineInfo.push_back(LineStartToIntelJITFormat( - reinterpret_cast(FnStart), - I->Address, - I->Loc)); - - // If we have no file name yet for the function, use the filename from - // the first instruction that has one - if (FunctionMessage.source_file_name == 0) { - MDNode *scope = I->Loc.getScope( - Details.MF->getFunction()->getContext()); - FunctionMessage.source_file_name = const_cast( - Filenames.getFullPath(scope)); - } - } - - FunctionMessage.line_number_size = LineInfo.size(); - FunctionMessage.line_number_table = &*LineInfo.begin(); - } else { - FunctionMessage.line_number_size = 0; - FunctionMessage.line_number_table = 0; - } + OwningBinary DebugObjOwner = L.getObjectForDebug(Obj); + const ObjectFile &DebugObj = *DebugObjOwner.getBinary(); - Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, - &FunctionMessage); - MethodIDs[FnStart] = FunctionMessage.method_id; -} - -void IntelJITEventListener::NotifyFreeingMachineCode(void *FnStart) { - MethodIDMap::iterator I = MethodIDs.find(FnStart); - if (I != MethodIDs.end()) { - Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START, &I->second); - MethodIDs.erase(I); - } -} - -void IntelJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) { // Get the address of the object image for use as a unique identifier - const void* ObjData = Obj.getData().data(); - DIContext* Context = DIContext::getDWARFContext(Obj.getObjectFile()); + const void* ObjData = DebugObj.getData().data(); + DIContext* Context = new DWARFContextInMemory(DebugObj); MethodAddressVector Functions; // Use symbol info to iterate functions in the object. - error_code ec; - for (object::symbol_iterator I = Obj.begin_symbols(), - E = Obj.end_symbols(); - I != E && !ec; - I.increment(ec)) { + for (const std::pair &P : computeSymbolSizes(DebugObj)) { + SymbolRef Sym = P.first; std::vector LineInfo; std::string SourceFileName; - object::SymbolRef::Type SymType; - if (I->getType(SymType)) continue; - if (SymType == object::SymbolRef::ST_Function) { - StringRef Name; - uint64_t Addr; - uint64_t Size; - if (I->getName(Name)) continue; - if (I->getAddress(Addr)) continue; - if (I->getSize(Size)) continue; - - // Record this address in a local vector - Functions.push_back((void*)Addr); - - // Build the function loaded notification message - iJIT_Method_Load FunctionMessage = FunctionDescToIntelJITFormat(*Wrapper, - Name.data(), - Addr, - Size); - if (Context) { - DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size); - DILineInfoTable::iterator Begin = Lines.begin(); - DILineInfoTable::iterator End = Lines.end(); - for (DILineInfoTable::iterator It = Begin; It != End; ++It) { - LineInfo.push_back(DILineInfoToIntelJITFormat((uintptr_t)Addr, - It->first, - It->second)); - } - if (LineInfo.size() == 0) { - FunctionMessage.source_file_name = 0; - FunctionMessage.line_number_size = 0; - FunctionMessage.line_number_table = 0; - } else { - SourceFileName = Lines.front().second.getFileName(); - FunctionMessage.source_file_name = (char *)SourceFileName.c_str(); - FunctionMessage.line_number_size = LineInfo.size(); - FunctionMessage.line_number_table = &*LineInfo.begin(); - } - } else { - FunctionMessage.source_file_name = 0; - FunctionMessage.line_number_size = 0; - FunctionMessage.line_number_table = 0; - } - - Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, - &FunctionMessage); - MethodIDs[(void*)Addr] = FunctionMessage.method_id; + if (Sym.getType() != SymbolRef::ST_Function) + continue; + + ErrorOr Name = Sym.getName(); + if (!Name) + continue; + + ErrorOr AddrOrErr = Sym.getAddress(); + if (AddrOrErr.getError()) + continue; + uint64_t Addr = *AddrOrErr; + uint64_t Size = P.second; + + // Record this address in a local vector + Functions.push_back((void*)Addr); + + // Build the function loaded notification message + iJIT_Method_Load FunctionMessage = + FunctionDescToIntelJITFormat(*Wrapper, Name->data(), Addr, Size); + DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size); + DILineInfoTable::iterator Begin = Lines.begin(); + DILineInfoTable::iterator End = Lines.end(); + for (DILineInfoTable::iterator It = Begin; It != End; ++It) { + LineInfo.push_back( + DILineInfoToIntelJITFormat((uintptr_t)Addr, It->first, It->second)); } + if (LineInfo.size() == 0) { + FunctionMessage.source_file_name = 0; + FunctionMessage.line_number_size = 0; + FunctionMessage.line_number_table = 0; + } else { + // Source line information for the address range is provided as + // a code offset for the start of the corresponding sub-range and + // a source line. JIT API treats offsets in LineNumberInfo structures + // as the end of the corresponding code region. The start of the code + // is taken from the previous element. Need to shift the elements. + + LineNumberInfo last = LineInfo.back(); + last.Offset = FunctionMessage.method_size; + LineInfo.push_back(last); + for (size_t i = LineInfo.size() - 2; i > 0; --i) + LineInfo[i].LineNumber = LineInfo[i - 1].LineNumber; + + SourceFileName = Lines.front().second.FileName; + FunctionMessage.source_file_name = + const_cast(SourceFileName.c_str()); + FunctionMessage.line_number_size = LineInfo.size(); + FunctionMessage.line_number_table = &*LineInfo.begin(); + } + + Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, + &FunctionMessage); + MethodIDs[(void*)Addr] = FunctionMessage.method_id; } // To support object unload notification, we need to keep a list of // registered function addresses for each loaded object. We will // use the MethodIDs map to get the registered ID for each function. LoadedObjectMap[ObjData] = Functions; + DebugObjects[Obj.getData().data()] = std::move(DebugObjOwner); } -void IntelJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) { +void IntelJITEventListener::NotifyFreeingObject(const ObjectFile &Obj) { + // This object may not have been registered with the listener. If it wasn't, + // bail out. + if (DebugObjects.find(Obj.getData().data()) == DebugObjects.end()) + return; + // Get the address of the object image for use as a unique identifier - const void* ObjData = Obj.getData().data(); + const ObjectFile &DebugObj = *DebugObjects[Obj.getData().data()].getBinary(); + const void* ObjData = DebugObj.getData().data(); // Get the object's function list from LoadedObjectMap ObjectMap::iterator OI = LoadedObjectMap.find(ObjData); @@ -282,6 +207,7 @@ void IntelJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) { // Erase the object from LoadedObjectMap LoadedObjectMap.erase(OI); + DebugObjects.erase(Obj.getData().data()); } } // anonymous namespace.