225 lines · cpp
1//===------- JITLoaderVTune.cpp - Register profiler objects -----*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Register objects for access by profilers via the VTune JIT interface.10//===----------------------------------------------------------------------===//11 12#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h"13#include "llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h"14 15#if LLVM_USE_INTEL_JITEVENTS16#include "IntelJITEventsWrapper.h"17#include "ittnotify.h"18#include <map>19 20using namespace llvm;21using namespace llvm::orc;22 23namespace {24class JITEventWrapper {25public:26 static std::unique_ptr<IntelJITEventsWrapper> Wrapper;27};28std::unique_ptr<IntelJITEventsWrapper> JITEventWrapper::Wrapper;29} // namespace30 31static Error registerJITLoaderVTuneRegisterImpl(const VTuneMethodBatch &MB) {32 const size_t StringsSize = MB.Strings.size();33 34 for (const auto &MethodInfo : MB.Methods) {35 iJIT_Method_Load MethodMessage;36 memset(&MethodMessage, 0, sizeof(iJIT_Method_Load));37 38 MethodMessage.method_id = MethodInfo.MethodID;39 if (MethodInfo.NameSI != 0 && MethodInfo.NameSI < StringsSize) {40 MethodMessage.method_name =41 const_cast<char *>(MB.Strings.at(MethodInfo.NameSI).data());42 } else {43 MethodMessage.method_name = NULL;44 }45 if (MethodInfo.ClassFileSI != 0 && MethodInfo.ClassFileSI < StringsSize) {46 MethodMessage.class_file_name =47 const_cast<char *>(MB.Strings.at(MethodInfo.ClassFileSI).data());48 } else {49 MethodMessage.class_file_name = NULL;50 }51 if (MethodInfo.SourceFileSI != 0 && MethodInfo.SourceFileSI < StringsSize) {52 MethodMessage.source_file_name =53 const_cast<char *>(MB.Strings.at(MethodInfo.SourceFileSI).data());54 } else {55 MethodMessage.source_file_name = NULL;56 }57 58 MethodMessage.method_load_address = MethodInfo.LoadAddr.toPtr<void *>();59 MethodMessage.method_size = MethodInfo.LoadSize;60 MethodMessage.class_id = 0;61 62 MethodMessage.user_data = NULL;63 MethodMessage.user_data_size = 0;64 MethodMessage.env = iJDE_JittingAPI;65 66 std::vector<LineNumberInfo> LineInfo;67 for (const auto &LInfo : MethodInfo.LineTable) {68 LineInfo.push_back(LineNumberInfo{LInfo.first, LInfo.second});69 }70 71 if (LineInfo.size() == 0) {72 MethodMessage.line_number_size = 0;73 MethodMessage.line_number_table = 0;74 } else {75 MethodMessage.line_number_size = LineInfo.size();76 MethodMessage.line_number_table = &*LineInfo.begin();77 }78 JITEventWrapper::Wrapper->iJIT_NotifyEvent(79 iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &MethodMessage);80 }81 82 return Error::success();83}84 85static void registerJITLoaderVTuneUnregisterImpl(86 const std::vector<std::pair<uint64_t, uint64_t>> &UM) {87 for (auto &Method : UM) {88 JITEventWrapper::Wrapper->iJIT_NotifyEvent(89 iJVM_EVENT_TYPE_METHOD_UNLOAD_START,90 const_cast<uint64_t *>(&Method.first));91 }92}93 94extern "C" llvm::orc::shared::CWrapperFunctionResult95llvm_orc_registerVTuneImpl(const char *ArgData, size_t ArgSize) {96 using namespace orc::shared;97 if (!JITEventWrapper::Wrapper)98 JITEventWrapper::Wrapper.reset(new IntelJITEventsWrapper);99 100 return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(101 ArgData, ArgSize, registerJITLoaderVTuneRegisterImpl)102 .release();103}104 105extern "C" llvm::orc::shared::CWrapperFunctionResult106llvm_orc_unregisterVTuneImpl(const char *ArgData, size_t ArgSize) {107 using namespace orc::shared;108 return WrapperFunction<void(SPSVTuneUnloadedMethodIDs)>::handle(109 ArgData, ArgSize, registerJITLoaderVTuneUnregisterImpl)110 .release();111}112 113// For Testing: following code comes from llvm-jitlistener.cpp in llvm tools114namespace {115using SourceLocations = std::vector<std::pair<std::string, unsigned int>>;116using NativeCodeMap = std::map<uint64_t, SourceLocations>;117NativeCodeMap ReportedDebugFuncs;118} // namespace119 120static int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) {121 switch (EventType) {122 case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: {123 if (!EventSpecificData) {124 errs() << "Error: The JIT event listener did not provide a event data.";125 return -1;126 }127 iJIT_Method_Load *msg = static_cast<iJIT_Method_Load *>(EventSpecificData);128 129 ReportedDebugFuncs[msg->method_id];130 131 outs() << "Method load [" << msg->method_id << "]: " << msg->method_name132 << ", Size = " << msg->method_size << "\n";133 134 for (unsigned int i = 0; i < msg->line_number_size; ++i) {135 if (!msg->line_number_table) {136 errs() << "A function with a non-zero line count had no line table.";137 return -1;138 }139 std::pair<std::string, unsigned int> loc(140 std::string(msg->source_file_name),141 msg->line_number_table[i].LineNumber);142 ReportedDebugFuncs[msg->method_id].push_back(loc);143 outs() << " Line info @ " << msg->line_number_table[i].Offset << ": "144 << msg->source_file_name << ", line "145 << msg->line_number_table[i].LineNumber << "\n";146 }147 outs() << "\n";148 } break;149 case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: {150 if (!EventSpecificData) {151 errs() << "Error: The JIT event listener did not provide a event data.";152 return -1;153 }154 unsigned int UnloadId =155 *reinterpret_cast<unsigned int *>(EventSpecificData);156 assert(1 == ReportedDebugFuncs.erase(UnloadId));157 outs() << "Method unload [" << UnloadId << "]\n";158 } break;159 default:160 break;161 }162 return 0;163}164 165static iJIT_IsProfilingActiveFlags IsProfilingActive(void) {166 // for testing, pretend we have an Intel Parallel Amplifier XE 2011167 // instance attached168 return iJIT_SAMPLING_ON;169}170 171static unsigned int GetNewMethodID(void) {172 static unsigned int id = 0;173 return ++id;174}175 176extern "C" llvm::orc::shared::CWrapperFunctionResult177llvm_orc_test_registerVTuneImpl(const char *ArgData, size_t ArgSize) {178 using namespace orc::shared;179 JITEventWrapper::Wrapper.reset(new IntelJITEventsWrapper(180 NotifyEvent, NULL, NULL, IsProfilingActive, 0, 0, GetNewMethodID));181 return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(182 ArgData, ArgSize, registerJITLoaderVTuneRegisterImpl)183 .release();184}185 186#else187 188using namespace llvm;189using namespace llvm::orc;190 191static Error unsupportedBatch(const VTuneMethodBatch &MB) {192 return llvm::make_error<StringError>("unsupported for Intel VTune",193 inconvertibleErrorCode());194}195 196static void unsuppported(const std::vector<std::pair<uint64_t, uint64_t>> &UM) {197 198}199 200extern "C" llvm::orc::shared::CWrapperFunctionResult201llvm_orc_registerVTuneImpl(const char *ArgData, size_t ArgSize) {202 using namespace orc::shared;203 return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(204 ArgData, ArgSize, unsupportedBatch)205 .release();206}207 208extern "C" llvm::orc::shared::CWrapperFunctionResult209llvm_orc_unregisterVTuneImpl(const char *ArgData, size_t ArgSize) {210 using namespace orc::shared;211 return WrapperFunction<void(SPSVTuneUnloadedMethodIDs)>::handle(212 ArgData, ArgSize, unsuppported)213 .release();214}215 216extern "C" llvm::orc::shared::CWrapperFunctionResult217llvm_orc_test_registerVTuneImpl(const char *ArgData, size_t ArgSize) {218 using namespace orc::shared;219 return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(220 ArgData, ArgSize, unsupportedBatch)221 .release();222}223 224#endif225