100f41216SHongyu Chen //===------- JITLoaderVTune.cpp - Register profiler objects -----*- C++ -*-===// 200f41216SHongyu Chen // 300f41216SHongyu Chen // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 400f41216SHongyu Chen // See https://llvm.org/LICENSE.txt for license information. 500f41216SHongyu Chen // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 600f41216SHongyu Chen // 700f41216SHongyu Chen //===----------------------------------------------------------------------===// 800f41216SHongyu Chen // 900f41216SHongyu Chen // Register objects for access by profilers via the VTune JIT interface. 1000f41216SHongyu Chen //===----------------------------------------------------------------------===// 1100f41216SHongyu Chen 1200f41216SHongyu Chen #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h" 1300f41216SHongyu Chen #include "llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h" 1400f41216SHongyu Chen 1500f41216SHongyu Chen #if LLVM_USE_INTEL_JITEVENTS 1600f41216SHongyu Chen #include "IntelJITEventsWrapper.h" 1700f41216SHongyu Chen #include "ittnotify.h" 18*bda39a60SKazu Hirata #include <map> 1900f41216SHongyu Chen 2000f41216SHongyu Chen using namespace llvm; 2100f41216SHongyu Chen using namespace llvm::orc; 2200f41216SHongyu Chen 2300f41216SHongyu Chen namespace { 2400f41216SHongyu Chen class JITEventWrapper { 2500f41216SHongyu Chen public: 2600f41216SHongyu Chen static std::unique_ptr<IntelJITEventsWrapper> Wrapper; 2700f41216SHongyu Chen }; 2800f41216SHongyu Chen std::unique_ptr<IntelJITEventsWrapper> JITEventWrapper::Wrapper; 2900f41216SHongyu Chen } // namespace 3000f41216SHongyu Chen 3100f41216SHongyu Chen static Error registerJITLoaderVTuneRegisterImpl(const VTuneMethodBatch &MB) { 3200f41216SHongyu Chen const size_t StringsSize = MB.Strings.size(); 3300f41216SHongyu Chen 3400f41216SHongyu Chen for (const auto &MethodInfo : MB.Methods) { 3500f41216SHongyu Chen iJIT_Method_Load MethodMessage; 3600f41216SHongyu Chen memset(&MethodMessage, 0, sizeof(iJIT_Method_Load)); 3700f41216SHongyu Chen 3800f41216SHongyu Chen MethodMessage.method_id = MethodInfo.MethodID; 3900f41216SHongyu Chen if (MethodInfo.NameSI != 0 && MethodInfo.NameSI < StringsSize) { 4000f41216SHongyu Chen MethodMessage.method_name = 4100f41216SHongyu Chen const_cast<char *>(MB.Strings.at(MethodInfo.NameSI).data()); 4200f41216SHongyu Chen } else { 4300f41216SHongyu Chen MethodMessage.method_name = NULL; 4400f41216SHongyu Chen } 4500f41216SHongyu Chen if (MethodInfo.ClassFileSI != 0 && MethodInfo.ClassFileSI < StringsSize) { 4600f41216SHongyu Chen MethodMessage.class_file_name = 4700f41216SHongyu Chen const_cast<char *>(MB.Strings.at(MethodInfo.ClassFileSI).data()); 4800f41216SHongyu Chen } else { 4900f41216SHongyu Chen MethodMessage.class_file_name = NULL; 5000f41216SHongyu Chen } 5100f41216SHongyu Chen if (MethodInfo.SourceFileSI != 0 && MethodInfo.SourceFileSI < StringsSize) { 5200f41216SHongyu Chen MethodMessage.source_file_name = 5300f41216SHongyu Chen const_cast<char *>(MB.Strings.at(MethodInfo.SourceFileSI).data()); 5400f41216SHongyu Chen } else { 5500f41216SHongyu Chen MethodMessage.source_file_name = NULL; 5600f41216SHongyu Chen } 5700f41216SHongyu Chen 5800f41216SHongyu Chen MethodMessage.method_load_address = MethodInfo.LoadAddr.toPtr<void *>(); 5900f41216SHongyu Chen MethodMessage.method_size = MethodInfo.LoadSize; 6000f41216SHongyu Chen MethodMessage.class_id = 0; 6100f41216SHongyu Chen 6200f41216SHongyu Chen MethodMessage.user_data = NULL; 6300f41216SHongyu Chen MethodMessage.user_data_size = 0; 6400f41216SHongyu Chen MethodMessage.env = iJDE_JittingAPI; 6500f41216SHongyu Chen 6600f41216SHongyu Chen std::vector<LineNumberInfo> LineInfo; 6700f41216SHongyu Chen for (const auto &LInfo : MethodInfo.LineTable) { 6800f41216SHongyu Chen LineInfo.push_back(LineNumberInfo{LInfo.first, LInfo.second}); 6900f41216SHongyu Chen } 7000f41216SHongyu Chen 7100f41216SHongyu Chen if (LineInfo.size() == 0) { 7200f41216SHongyu Chen MethodMessage.line_number_size = 0; 7300f41216SHongyu Chen MethodMessage.line_number_table = 0; 7400f41216SHongyu Chen } else { 7500f41216SHongyu Chen MethodMessage.line_number_size = LineInfo.size(); 7600f41216SHongyu Chen MethodMessage.line_number_table = &*LineInfo.begin(); 7700f41216SHongyu Chen } 7800f41216SHongyu Chen JITEventWrapper::Wrapper->iJIT_NotifyEvent( 7900f41216SHongyu Chen iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &MethodMessage); 8000f41216SHongyu Chen } 8100f41216SHongyu Chen 8200f41216SHongyu Chen return Error::success(); 8300f41216SHongyu Chen } 8400f41216SHongyu Chen 8500f41216SHongyu Chen static void registerJITLoaderVTuneUnregisterImpl( 8600f41216SHongyu Chen const std::vector<std::pair<uint64_t, uint64_t>> &UM) { 8700f41216SHongyu Chen for (auto &Method : UM) { 8800f41216SHongyu Chen JITEventWrapper::Wrapper->iJIT_NotifyEvent( 8900f41216SHongyu Chen iJVM_EVENT_TYPE_METHOD_UNLOAD_START, 9035f5caeaSChen Cheng const_cast<uint64_t *>(&Method.first)); 9100f41216SHongyu Chen } 9200f41216SHongyu Chen } 9300f41216SHongyu Chen 9400f41216SHongyu Chen extern "C" llvm::orc::shared::CWrapperFunctionResult 9500f41216SHongyu Chen llvm_orc_registerVTuneImpl(const char *Data, uint64_t Size) { 9600f41216SHongyu Chen using namespace orc::shared; 9700f41216SHongyu Chen if (!JITEventWrapper::Wrapper) 9800f41216SHongyu Chen JITEventWrapper::Wrapper.reset(new IntelJITEventsWrapper); 9900f41216SHongyu Chen 10000f41216SHongyu Chen return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle( 10100f41216SHongyu Chen Data, Size, registerJITLoaderVTuneRegisterImpl) 10200f41216SHongyu Chen .release(); 10300f41216SHongyu Chen } 10400f41216SHongyu Chen 10500f41216SHongyu Chen extern "C" llvm::orc::shared::CWrapperFunctionResult 10600f41216SHongyu Chen llvm_orc_unregisterVTuneImpl(const char *Data, uint64_t Size) { 10700f41216SHongyu Chen using namespace orc::shared; 10800f41216SHongyu Chen return WrapperFunction<void(SPSVTuneUnloadedMethodIDs)>::handle( 10900f41216SHongyu Chen Data, Size, registerJITLoaderVTuneUnregisterImpl) 11000f41216SHongyu Chen .release(); 11100f41216SHongyu Chen } 11200f41216SHongyu Chen 11300f41216SHongyu Chen // For Testing: following code comes from llvm-jitlistener.cpp in llvm tools 11400f41216SHongyu Chen namespace { 11500f41216SHongyu Chen using SourceLocations = std::vector<std::pair<std::string, unsigned int>>; 11600f41216SHongyu Chen using NativeCodeMap = std::map<uint64_t, SourceLocations>; 11700f41216SHongyu Chen NativeCodeMap ReportedDebugFuncs; 11800f41216SHongyu Chen } // namespace 11900f41216SHongyu Chen 12000f41216SHongyu Chen static int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) { 12100f41216SHongyu Chen switch (EventType) { 12200f41216SHongyu Chen case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: { 12300f41216SHongyu Chen if (!EventSpecificData) { 12400f41216SHongyu Chen errs() << "Error: The JIT event listener did not provide a event data."; 12500f41216SHongyu Chen return -1; 12600f41216SHongyu Chen } 12700f41216SHongyu Chen iJIT_Method_Load *msg = static_cast<iJIT_Method_Load *>(EventSpecificData); 12800f41216SHongyu Chen 12900f41216SHongyu Chen ReportedDebugFuncs[msg->method_id]; 13000f41216SHongyu Chen 13100f41216SHongyu Chen outs() << "Method load [" << msg->method_id << "]: " << msg->method_name 13200f41216SHongyu Chen << ", Size = " << msg->method_size << "\n"; 13300f41216SHongyu Chen 13400f41216SHongyu Chen for (unsigned int i = 0; i < msg->line_number_size; ++i) { 13500f41216SHongyu Chen if (!msg->line_number_table) { 13600f41216SHongyu Chen errs() << "A function with a non-zero line count had no line table."; 13700f41216SHongyu Chen return -1; 13800f41216SHongyu Chen } 13900f41216SHongyu Chen std::pair<std::string, unsigned int> loc( 14000f41216SHongyu Chen std::string(msg->source_file_name), 14100f41216SHongyu Chen msg->line_number_table[i].LineNumber); 14200f41216SHongyu Chen ReportedDebugFuncs[msg->method_id].push_back(loc); 14300f41216SHongyu Chen outs() << " Line info @ " << msg->line_number_table[i].Offset << ": " 14400f41216SHongyu Chen << msg->source_file_name << ", line " 14500f41216SHongyu Chen << msg->line_number_table[i].LineNumber << "\n"; 14600f41216SHongyu Chen } 14700f41216SHongyu Chen outs() << "\n"; 14800f41216SHongyu Chen } break; 14900f41216SHongyu Chen case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: { 15000f41216SHongyu Chen if (!EventSpecificData) { 15100f41216SHongyu Chen errs() << "Error: The JIT event listener did not provide a event data."; 15200f41216SHongyu Chen return -1; 15300f41216SHongyu Chen } 15400f41216SHongyu Chen unsigned int UnloadId = 15500f41216SHongyu Chen *reinterpret_cast<unsigned int *>(EventSpecificData); 15600f41216SHongyu Chen assert(1 == ReportedDebugFuncs.erase(UnloadId)); 15700f41216SHongyu Chen outs() << "Method unload [" << UnloadId << "]\n"; 15800f41216SHongyu Chen } break; 15900f41216SHongyu Chen default: 16000f41216SHongyu Chen break; 16100f41216SHongyu Chen } 16200f41216SHongyu Chen return 0; 16300f41216SHongyu Chen } 16400f41216SHongyu Chen 16500f41216SHongyu Chen static iJIT_IsProfilingActiveFlags IsProfilingActive(void) { 16600f41216SHongyu Chen // for testing, pretend we have an Intel Parallel Amplifier XE 2011 16700f41216SHongyu Chen // instance attached 16800f41216SHongyu Chen return iJIT_SAMPLING_ON; 16900f41216SHongyu Chen } 17000f41216SHongyu Chen 17100f41216SHongyu Chen static unsigned int GetNewMethodID(void) { 17200f41216SHongyu Chen static unsigned int id = 0; 17300f41216SHongyu Chen return ++id; 17400f41216SHongyu Chen } 17500f41216SHongyu Chen 17600f41216SHongyu Chen extern "C" llvm::orc::shared::CWrapperFunctionResult 17700f41216SHongyu Chen llvm_orc_test_registerVTuneImpl(const char *Data, uint64_t Size) { 17800f41216SHongyu Chen using namespace orc::shared; 17900f41216SHongyu Chen JITEventWrapper::Wrapper.reset(new IntelJITEventsWrapper( 18000f41216SHongyu Chen NotifyEvent, NULL, NULL, IsProfilingActive, 0, 0, GetNewMethodID)); 18100f41216SHongyu Chen return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle( 18200f41216SHongyu Chen Data, Size, registerJITLoaderVTuneRegisterImpl) 18300f41216SHongyu Chen .release(); 18400f41216SHongyu Chen } 18500f41216SHongyu Chen 18600f41216SHongyu Chen #else 18700f41216SHongyu Chen 18800f41216SHongyu Chen using namespace llvm; 18900f41216SHongyu Chen using namespace llvm::orc; 19000f41216SHongyu Chen 19100f41216SHongyu Chen static Error unsupportedBatch(const VTuneMethodBatch &MB) { 19200f41216SHongyu Chen return llvm::make_error<StringError>("unsupported for Intel VTune", 19300f41216SHongyu Chen inconvertibleErrorCode()); 19400f41216SHongyu Chen } 19500f41216SHongyu Chen 19600f41216SHongyu Chen static void unsuppported(const std::vector<std::pair<uint64_t, uint64_t>> &UM) { 19700f41216SHongyu Chen 19800f41216SHongyu Chen } 19900f41216SHongyu Chen 20000f41216SHongyu Chen extern "C" llvm::orc::shared::CWrapperFunctionResult 20100f41216SHongyu Chen llvm_orc_registerVTuneImpl(const char *Data, uint64_t Size) { 20200f41216SHongyu Chen using namespace orc::shared; 20300f41216SHongyu Chen return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle( 20400f41216SHongyu Chen Data, Size, unsupportedBatch) 20500f41216SHongyu Chen .release(); 20600f41216SHongyu Chen } 20700f41216SHongyu Chen 20800f41216SHongyu Chen extern "C" llvm::orc::shared::CWrapperFunctionResult 20900f41216SHongyu Chen llvm_orc_unregisterVTuneImpl(const char *Data, uint64_t Size) { 21000f41216SHongyu Chen using namespace orc::shared; 21100f41216SHongyu Chen return WrapperFunction<void(SPSVTuneUnloadedMethodIDs)>::handle(Data, Size, 21200f41216SHongyu Chen unsuppported) 21300f41216SHongyu Chen .release(); 21400f41216SHongyu Chen } 21500f41216SHongyu Chen 21600f41216SHongyu Chen extern "C" llvm::orc::shared::CWrapperFunctionResult 21700f41216SHongyu Chen llvm_orc_test_registerVTuneImpl(const char *Data, uint64_t Size) { 21800f41216SHongyu Chen using namespace orc::shared; 21900f41216SHongyu Chen return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle( 22000f41216SHongyu Chen Data, Size, unsupportedBatch) 22100f41216SHongyu Chen .release(); 22200f41216SHongyu Chen } 22300f41216SHongyu Chen 22400f41216SHongyu Chen #endif 225