diff --git a/llvm/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt b/llvm/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt --- a/llvm/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt +++ b/llvm/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt @@ -1,5 +1,26 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. ) +set(GIT_REPOSITORY https://github.com/intel/ittapi.git) +set(GIT_TAG v3.18.8) + +if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/ittapi) + execute_process(COMMAND ${GIT_EXECUTABLE} clone ${GIT_REPOSITORY} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + RESULT_VARIABLE GIT_CLONE_RESULT) + if(NOT GIT_CLONE_RESULT EQUAL "0") + message(FATAL_ERROR "git clone ${GIT_REPOSITORY} failed with ${GIT_CLONE_RESULT}, please clone ${GIT_REPOSITORY}") + endif() +endif() + +execute_process(COMMAND ${GIT_EXECUTABLE} checkout ${GIT_TAG} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ittapi + RESULT_VARIABLE GIT_CHECKOUT_RESULT) +if(NOT GIT_CHECKOUT_RESULT EQUAL "0") + message(FATAL_ERROR "git checkout ${GIT_TAG} failed with ${GIT_CHECKOUT_RESULT}, please checkout ${GIT_TAG} at ${CMAKE_CURRENT_SOURCE_DIR}/ittapi") +endif() + +include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/ittapi/include/ ) + if( HAVE_LIBDL ) set(LLVM_INTEL_JIT_LIBS ${CMAKE_DL_LIBS}) endif() @@ -10,6 +31,7 @@ add_llvm_component_library(LLVMIntelJITEvents IntelJITEventListener.cpp jitprofiling.c + ittapi/src/ittnotify/ittnotify_static.c LINK_LIBS ${LLVM_INTEL_JIT_LIBS} ) diff --git a/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp b/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp --- a/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp +++ b/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "IntelJITEventsWrapper.h" +#include "ittnotify.h" #include "llvm-c/ExecutionEngine.h" #include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/MachineFunction.h" @@ -36,6 +37,86 @@ namespace { +class IntelIttnotifyInfo { + std::string ModuleName; + std::vector SectionNamesVector; + std::vector<__itt_section_info> SectionInfoVector; + __itt_module_object *ModuleObject; + IntelJITEventsWrapper &WrapperRef; + +public: + IntelIttnotifyInfo(IntelJITEventsWrapper &Wrapper) + : ModuleObject(NULL), WrapperRef(Wrapper){}; + ~IntelIttnotifyInfo() { delete ModuleObject; }; + + void setModuleName(const char *Name) { ModuleName = std::string(Name); } + + const char *getModuleName() { return ModuleName.c_str(); } + + void setModuleObject(__itt_module_object *ModuleObj) { + ModuleObject = ModuleObj; + } + + __itt_module_object *getModuleObject() { return ModuleObject; } + + __itt_section_info *getSectionInfoVectorBegin() { + if (SectionInfoVector.size()) + return &SectionInfoVector[0]; + return NULL; + } + + void reportSection(llvm::IttEventType EventType, const char *SectionName, + unsigned int SectionSize) { + WrapperRef.iJitIttNotifyInfo(EventType, SectionName, SectionSize); + } + + int fillSectionInformation(const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) { + + int SectionCounter = 0; + + for (auto &Section : Obj.sections()) { + uint64_t SectionLoadAddr = L.getSectionLoadAddress(Section); + if (SectionLoadAddr) { + object::ELFSectionRef ElfSection(Section); + + __itt_section_info SectionInfo; + memset(&SectionInfo, 0, sizeof(SectionInfo)); + SectionInfo.start_addr = reinterpret_cast(SectionLoadAddr); + SectionInfo.file_offset = ElfSection.getOffset(); + SectionInfo.flags = ElfSection.getFlags(); + + StringRef SectionName(""); + auto SectionNameOrError = ElfSection.getName(); + if (SectionNameOrError) + SectionName = *SectionNameOrError; + + SectionNamesVector.push_back(SectionName.str()); + SectionInfo.size = ElfSection.getSize(); + reportSection(llvm::LoadBinarySection, SectionName.str().c_str(), + SectionInfo.size); + + if (ElfSection.isBSS()) { + SectionInfo.type = itt_section_type_bss; + } else if (ElfSection.isData()) { + SectionInfo.type = itt_section_type_data; + } else if (ElfSection.isText()) { + SectionInfo.type = itt_section_type_text; + } + SectionInfoVector.push_back(SectionInfo); + ++SectionCounter; + } + } + // Hereinafter: don't change SectionNamesVector content to avoid vector + // reallocation - reallocation invalidates all the references, pointers, and + // iterators referring to the elements in the sequence. + for (int I = 0; I < SectionCounter; ++I) { + SectionInfoVector[I].name = SectionNamesVector[I].c_str(); + } + return SectionCounter; + } +}; + class IntelJITEventListener : public JITEventListener { typedef DenseMap MethodIDMap; @@ -48,6 +129,8 @@ ObjectMap LoadedObjectMap; std::map> DebugObjects; + std::map> KeyToIttnotify; + public: IntelJITEventListener(IntelJITEventsWrapper* libraryWrapper) { Wrapper.reset(libraryWrapper); @@ -95,146 +178,205 @@ return Result; } +int getBackwardCompatibilityMode() { + + char *BackwardCompatibilityEnv = getenv("INTEL_JIT_BACKWARD_COMPATIBILITY"); + int BackwardCompatibilityMode = 0; + if (BackwardCompatibilityEnv) { + StringRef(BackwardCompatibilityEnv) + .getAsInteger(10, BackwardCompatibilityMode); + } + return BackwardCompatibilityMode; +} + void IntelJITEventListener::notifyObjectLoaded( ObjectKey Key, const ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &L) { - OwningBinary DebugObjOwner = L.getObjectForDebug(Obj); - const ObjectFile *DebugObj = DebugObjOwner.getBinary(); - if (!DebugObj) - return; - - // Get the address of the object image for use as a unique identifier - const void* ObjData = DebugObj->getData().data(); - std::unique_ptr Context = DWARFContext::create(*DebugObj); - MethodAddressVector Functions; - - // Use symbol info to iterate functions in the object. - for (const std::pair &P : computeSymbolSizes(*DebugObj)) { - SymbolRef Sym = P.first; - std::vector LineInfo; - std::string SourceFileName; - - Expected SymTypeOrErr = Sym.getType(); - if (!SymTypeOrErr) { - // TODO: Actually report errors helpfully. - consumeError(SymTypeOrErr.takeError()); - continue; + int BackwardCompatibilityMode = getBackwardCompatibilityMode(); + if (BackwardCompatibilityMode == 0) { + if (Obj.isELF()) { + std::unique_ptr ModuleIttnotify = + std::make_unique(*Wrapper); + ModuleIttnotify->setModuleName( + StringRef(llvm::utohexstr( + MD5Hash(Obj.getMemoryBufferRef().getBuffer()), true)) + .str() + .c_str()); + + __itt_module_object *ModuleObject = new __itt_module_object(); + ModuleObject->module_name = ModuleIttnotify->getModuleName(); + ModuleObject->module_size = Obj.getMemoryBufferRef().getBufferSize(); + Wrapper->iJitIttNotifyInfo(llvm::LoadBinaryModule, + ModuleObject->module_name, + ModuleObject->module_size); + ModuleObject->module_type = __itt_module_type_elf; + ModuleObject->section_number = + ModuleIttnotify->fillSectionInformation(Obj, L); + ModuleObject->module_buffer = + (void *)const_cast(Obj.getMemoryBufferRef().getBufferStart()); + ModuleObject->module_id = + __itt_id_make((void *)&(*ModuleObject), ModuleObject->module_size); + ModuleObject->section_array = + ModuleIttnotify->getSectionInfoVectorBegin(); + ModuleIttnotify->setModuleObject(ModuleObject); + + __itt_module_load_with_sections(ModuleObject); + + KeyToIttnotify[Key] = std::move(ModuleIttnotify); } - SymbolRef::Type SymType = *SymTypeOrErr; - if (SymType != SymbolRef::ST_Function) - continue; - - Expected Name = Sym.getName(); - if (!Name) { - // TODO: Actually report errors helpfully. - consumeError(Name.takeError()); - continue; + } else if (BackwardCompatibilityMode == 1) { + + OwningBinary DebugObjOwner = L.getObjectForDebug(Obj); + const ObjectFile *DebugObj = DebugObjOwner.getBinary(); + if (!DebugObj) + return; + + // Get the address of the object image for use as a unique identifier + const void *ObjData = DebugObj->getData().data(); + std::unique_ptr Context = DWARFContext::create(*DebugObj); + MethodAddressVector Functions; + + // Use symbol info to iterate functions in the object. + for (const std::pair &P : + computeSymbolSizes(*DebugObj)) { + SymbolRef Sym = P.first; + std::vector LineInfo; + std::string SourceFileName; + + Expected SymTypeOrErr = Sym.getType(); + if (!SymTypeOrErr) { + // TODO: Actually report errors helpfully. + consumeError(SymTypeOrErr.takeError()); + continue; + } + SymbolRef::Type SymType = *SymTypeOrErr; + if (SymType != SymbolRef::ST_Function) + continue; + + Expected Name = Sym.getName(); + if (!Name) { + // TODO: Actually report errors helpfully. + consumeError(Name.takeError()); + continue; + } + + Expected AddrOrErr = Sym.getAddress(); + if (!AddrOrErr) { + // TODO: Actually report errors helpfully. + consumeError(AddrOrErr.takeError()); + continue; + } + uint64_t Addr = *AddrOrErr; + uint64_t Size = P.second; + + auto SecOrErr = Sym.getSection(); + if (!SecOrErr) { + // TODO: Actually report errors helpfully. + consumeError(SecOrErr.takeError()); + continue; + } + object::section_iterator Sec = *SecOrErr; + if (Sec == Obj.section_end()) + continue; + uint64_t Index = Sec->getIndex(); + + // 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, Index}, 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; } - Expected AddrOrErr = Sym.getAddress(); - if (!AddrOrErr) { - // TODO: Actually report errors helpfully. - consumeError(AddrOrErr.takeError()); - continue; - } - uint64_t Addr = *AddrOrErr; - uint64_t Size = P.second; - - auto SecOrErr = Sym.getSection(); - if (!SecOrErr) { - // TODO: Actually report errors helpfully. - consumeError(SecOrErr.takeError()); - continue; - } - object::section_iterator Sec = *SecOrErr; - if (Sec == Obj.section_end()) - continue; - uint64_t Index = Sec->getIndex(); - - // 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, Index}, 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[Key] = std::move(DebugObjOwner); } - - // 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[Key] = std::move(DebugObjOwner); } void IntelJITEventListener::notifyFreeingObject(ObjectKey Key) { - // This object may not have been registered with the listener. If it wasn't, - // bail out. - if (DebugObjects.find(Key) == DebugObjects.end()) - return; - - // Get the address of the object image for use as a unique identifier - const ObjectFile &DebugObj = *DebugObjects[Key].getBinary(); - const void* ObjData = DebugObj.getData().data(); - - // Get the object's function list from LoadedObjectMap - ObjectMap::iterator OI = LoadedObjectMap.find(ObjData); - if (OI == LoadedObjectMap.end()) - return; - MethodAddressVector& Functions = OI->second; - - // Walk the function list, unregistering each function - for (MethodAddressVector::iterator FI = Functions.begin(), - FE = Functions.end(); - FI != FE; - ++FI) { - void* FnStart = const_cast(*FI); - MethodIDMap::iterator MI = MethodIDs.find(FnStart); - if (MI != MethodIDs.end()) { - Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START, - &MI->second); - MethodIDs.erase(MI); + + int BackwardCompatibilityMode = getBackwardCompatibilityMode(); + if (BackwardCompatibilityMode == 0) { + if (KeyToIttnotify.find(Key) == KeyToIttnotify.end()) + return; + __itt_module_unload_with_sections(KeyToIttnotify[Key]->getModuleObject()); + Wrapper->iJitIttNotifyInfo( + llvm::UnloadBinaryModule, + KeyToIttnotify[Key]->getModuleObject()->module_name, + KeyToIttnotify[Key]->getModuleObject()->module_size); + KeyToIttnotify.erase(Key); + } else if (BackwardCompatibilityMode == 1) { + // This object may not have been registered with the listener. If it wasn't, + // bail out. + if (DebugObjects.find(Key) == DebugObjects.end()) + return; + + // Get the address of the object image for use as a unique identifier + const ObjectFile &DebugObj = *DebugObjects[Key].getBinary(); + const void *ObjData = DebugObj.getData().data(); + + // Get the object's function list from LoadedObjectMap + ObjectMap::iterator OI = LoadedObjectMap.find(ObjData); + if (OI == LoadedObjectMap.end()) + return; + MethodAddressVector &Functions = OI->second; + + // Walk the function list, unregistering each function + for (MethodAddressVector::iterator FI = Functions.begin(), + FE = Functions.end(); + FI != FE; ++FI) { + void *FnStart = const_cast(*FI); + MethodIDMap::iterator MI = MethodIDs.find(FnStart); + if (MI != MethodIDs.end()) { + Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START, + &MI->second); + MethodIDs.erase(MI); + } } - } - // Erase the object from LoadedObjectMap - LoadedObjectMap.erase(OI); - DebugObjects.erase(Key); + // Erase the object from LoadedObjectMap + LoadedObjectMap.erase(OI); + DebugObjects.erase(Key); + } } } // anonymous namespace. diff --git a/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h b/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h --- a/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h +++ b/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h @@ -21,10 +21,18 @@ namespace llvm { +typedef enum { + LoadBinaryModule, + LoadBinarySection, + UnloadBinaryModule, + UnloadBinarySection +} IttEventType; + class IntelJITEventsWrapper { // Function pointer types for testing implementation of Intel jitprofiling // library typedef int (*NotifyEventPtr)(iJIT_JVM_EVENT, void*); + typedef int (*IttnotifyInfoPtr)(IttEventType, const char *, unsigned int); typedef void (*RegisterCallbackExPtr)(void *, iJIT_ModeChangedEx ); typedef iJIT_IsProfilingActiveFlags (*IsProfilingActivePtr)(void); typedef void (*FinalizeThreadPtr)(void); @@ -32,6 +40,7 @@ typedef unsigned int (*GetNewMethodIDPtr)(void); NotifyEventPtr NotifyEventFunc; + IttnotifyInfoPtr IttnotifyInfoFunc; RegisterCallbackExPtr RegisterCallbackExFunc; IsProfilingActivePtr IsProfilingActiveFunc; GetNewMethodIDPtr GetNewMethodIDFunc; @@ -42,23 +51,22 @@ } IntelJITEventsWrapper() - : NotifyEventFunc(::iJIT_NotifyEvent), - RegisterCallbackExFunc(::iJIT_RegisterCallbackEx), - IsProfilingActiveFunc(::iJIT_IsProfilingActive), - GetNewMethodIDFunc(::iJIT_GetNewMethodID) { - } + : NotifyEventFunc(::iJIT_NotifyEvent), IttnotifyInfoFunc(0), + RegisterCallbackExFunc(::iJIT_RegisterCallbackEx), + IsProfilingActiveFunc(::iJIT_IsProfilingActive), + GetNewMethodIDFunc(::iJIT_GetNewMethodID) {} IntelJITEventsWrapper(NotifyEventPtr NotifyEventImpl, - RegisterCallbackExPtr RegisterCallbackExImpl, - IsProfilingActivePtr IsProfilingActiveImpl, - FinalizeThreadPtr FinalizeThreadImpl, - FinalizeProcessPtr FinalizeProcessImpl, - GetNewMethodIDPtr GetNewMethodIDImpl) - : NotifyEventFunc(NotifyEventImpl), - RegisterCallbackExFunc(RegisterCallbackExImpl), - IsProfilingActiveFunc(IsProfilingActiveImpl), - GetNewMethodIDFunc(GetNewMethodIDImpl) { - } + IttnotifyInfoPtr IttnotifyInfoImpl, + RegisterCallbackExPtr RegisterCallbackExImpl, + IsProfilingActivePtr IsProfilingActiveImpl, + FinalizeThreadPtr FinalizeThreadImpl, + FinalizeProcessPtr FinalizeProcessImpl, + GetNewMethodIDPtr GetNewMethodIDImpl) + : NotifyEventFunc(NotifyEventImpl), IttnotifyInfoFunc(IttnotifyInfoImpl), + RegisterCallbackExFunc(RegisterCallbackExImpl), + IsProfilingActiveFunc(IsProfilingActiveImpl), + GetNewMethodIDFunc(GetNewMethodIDImpl) {} // Sends an event announcing that a function has been emitted // return values are event-specific. See Intel documentation for details. @@ -68,6 +76,13 @@ return NotifyEventFunc(EventType, EventSpecificData); } + int iJitIttNotifyInfo(IttEventType EventType, const char *Name, + unsigned int Size) { + if (!IttnotifyInfoFunc) + return -1; + return IttnotifyInfoFunc(EventType, Name, Size); + } + // Registers a callback function to receive notice of profiling state changes void iJIT_RegisterCallbackEx(void *UserData, iJIT_ModeChangedEx NewModeCallBackFuncEx) { diff --git a/llvm/test/IttListener/lit.local.cfg b/llvm/test/IttListener/lit.local.cfg new file mode 100644 --- /dev/null +++ b/llvm/test/IttListener/lit.local.cfg @@ -0,0 +1,2 @@ +if not config.root.llvm_use_intel_jitevents: + config.unsupported = True diff --git a/llvm/test/IttListener/simple.ll b/llvm/test/IttListener/simple.ll new file mode 100644 --- /dev/null +++ b/llvm/test/IttListener/simple.ll @@ -0,0 +1,51 @@ +; Verify the behavior of the IntelJITEventListener. +; RUN: llvm-jitlistener %s | FileCheck %s + +; This test was created using the following file: +; +; 1: int foo(int a) { +; 2: return a; +; 3: } +; + +; CHECK: Module loaded : Name = {{.*}}, Size = {{[0-9]+}} +; CHECK: Loaded section : Name = .text, Size = {{[0-9]+}} +; CHECK: Loaded section : Name = .eh_frame, Size = {{[0-9]+}} +; CHECK: Module unloaded : Name = {{.*}}, Size = {{[0-9]+}} + +; Function Attrs: nounwind uwtable +define i32 @foo(i32 %a) #0 !dbg !4 { +entry: + %a.addr = alloca i32, align 4 + store i32 %a, i32* %a.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !12, metadata !13), !dbg !14 + %0 = load i32, i32* %a.addr, align 4, !dbg !15 + ret i32 %0, !dbg !16 +} + +; Function Attrs: nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!9, !10} +!llvm.ident = !{!11} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.6.0 (trunk)", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) +!1 = !DIFile(filename: "simple.c", directory: "F:\5Cusers\5Cakaylor\5Cllvm-s\5Cllvm\5Ctest\5CJitListener") +!2 = !{} +!4 = distinct !DISubprogram(name: "foo", line: 1, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 1, file: !1, scope: !5, type: !6, retainedNodes: !2) +!5 = !DIFile(filename: "simple.c", directory: "F:CusersCakaylorCllvm-sCllvmCtestCJitListener") +!6 = !DISubroutineType(types: !7) +!7 = !{!8, !8} +!8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!9 = !{i32 2, !"Dwarf Version", i32 4} +!10 = !{i32 2, !"Debug Info Version", i32 3} +!11 = !{!"clang version 3.6.0 (trunk)"} +!12 = !DILocalVariable(name: "a", line: 1, arg: 1, scope: !4, file: !5, type: !8) +!13 = !DIExpression() +!14 = !DILocation(line: 1, column: 13, scope: !4) +!15 = !DILocation(line: 2, column: 10, scope: !4) +!16 = !DILocation(line: 2, column: 3, scope: !4) diff --git a/llvm/test/JitListener/lit.local.cfg b/llvm/test/JitListener/lit.local.cfg --- a/llvm/test/JitListener/lit.local.cfg +++ b/llvm/test/JitListener/lit.local.cfg @@ -1,2 +1,3 @@ if not config.root.llvm_use_intel_jitevents: config.unsupported = True +config.environment['INTEL_JIT_BACKWARD_COMPATIBILITY'] = '1' diff --git a/llvm/tools/llvm-jitlistener/llvm-jitlistener.cpp b/llvm/tools/llvm-jitlistener/llvm-jitlistener.cpp --- a/llvm/tools/llvm-jitlistener/llvm-jitlistener.cpp +++ b/llvm/tools/llvm-jitlistener/llvm-jitlistener.cpp @@ -88,6 +88,46 @@ return 0; } +int ittNotifyInfo(IttEventType EventType, const char *Name, unsigned int Size) { + switch (EventType) { + case LoadBinaryModule: { + if (!Name) { + errs() << "Error: The IttNotify event listener did not provide a module " + "name."; + return -1; + } + outs() << "Module loaded : Name = " << Name << ", Size = " << Size << "\n"; + } break; + case LoadBinarySection: { + if (!Name) { + errs() << "Error: The IttNotify event listener did not provide a section " + "name."; + return -1; + } + outs() << "Loaded section : Name = " << Name << ", Size = " << Size << "\n"; + } break; + case UnloadBinaryModule: { + if (!Name) { + errs() << "Error: The IttNotify event listener did not provide a module " + "name."; + return -1; + } + outs() << "Module unloaded : Name = " << Name << ", Size = " << Size + << "\n"; + } break; + case UnloadBinarySection: { + if (!Name) { + errs() << "Error: The IttNotify event listener did not provide a section " + "name."; + return -1; + } + outs() << "Unloaded section : Name = " << Name << ", Size = " << Size + << "\n"; + } break; + } + return 0; +} + iJIT_IsProfilingActiveFlags IsProfilingActive(void) { // for testing, pretend we have an Intel Parallel Amplifier XE 2011 // instance attached @@ -155,7 +195,8 @@ std::unique_ptr Listener( JITEventListener::createIntelJITEventListener(new IntelJITEventsWrapper( - NotifyEvent, 0, IsProfilingActive, 0, 0, GetNewMethodID))); + NotifyEvent, ittNotifyInfo, 0, IsProfilingActive, 0, 0, + GetNewMethodID))); TheJIT->RegisterJITEventListener(Listener.get());