187 lines · cpp
1//===--- VTuneSupportPlugin.cpp -- Support for VTune profiler --*- 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// Handles support for registering code with VIntel Tune's Amplfiier JIT API.10//11//===----------------------------------------------------------------------===//12#include "llvm/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.h"13#include "llvm/DebugInfo/DWARF/DWARFContext.h"14#include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h"15 16using namespace llvm;17using namespace llvm::orc;18using namespace llvm::jitlink;19 20static constexpr StringRef RegisterVTuneImplName = "llvm_orc_registerVTuneImpl";21static constexpr StringRef UnregisterVTuneImplName =22 "llvm_orc_unregisterVTuneImpl";23static constexpr StringRef RegisterTestVTuneImplName =24 "llvm_orc_test_registerVTuneImpl";25 26static VTuneMethodBatch getMethodBatch(LinkGraph &G, bool EmitDebugInfo) {27 VTuneMethodBatch Batch;28 std::unique_ptr<DWARFContext> DC;29 StringMap<std::unique_ptr<MemoryBuffer>> DCBacking;30 if (EmitDebugInfo) {31 auto EDC = createDWARFContext(G);32 if (!EDC) {33 EmitDebugInfo = false;34 } else {35 DC = std::move(EDC->first);36 DCBacking = std::move(EDC->second);37 }38 }39 40 auto GetStringIdx = [Deduplicator = StringMap<uint32_t>(),41 &Batch](StringRef S) mutable {42 auto [I, Inserted] = Deduplicator.try_emplace(S);43 if (Inserted) {44 Batch.Strings.push_back(S.str());45 I->second = Batch.Strings.size();46 }47 return I->second;48 };49 for (auto Sym : G.defined_symbols()) {50 if (!Sym->isCallable())51 continue;52 53 Batch.Methods.push_back(VTuneMethodInfo());54 auto &Method = Batch.Methods.back();55 Method.MethodID = 0;56 Method.ParentMI = 0;57 Method.LoadAddr = Sym->getAddress();58 Method.LoadSize = Sym->getSize();59 Method.NameSI = GetStringIdx(*Sym->getName());60 Method.ClassFileSI = 0;61 Method.SourceFileSI = 0;62 63 if (!EmitDebugInfo)64 continue;65 66 auto &Section = Sym->getSection();67 auto Addr = Sym->getAddress();68 auto SAddr =69 object::SectionedAddress{Addr.getValue(), Section.getOrdinal()};70 DILineInfoTable LinesInfo = DC->getLineInfoForAddressRange(71 SAddr, Sym->getSize(),72 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath);73 Method.SourceFileSI = Batch.Strings.size();74 Batch.Strings.push_back(75 DC->getLineInfoForAddress(SAddr).value_or(DILineInfo()).FileName);76 for (auto &LInfo : LinesInfo) {77 Method.LineTable.push_back(78 std::pair<unsigned, unsigned>{/*unsigned*/ Sym->getOffset(),79 /*DILineInfo*/ LInfo.second.Line});80 }81 }82 return Batch;83}84 85void VTuneSupportPlugin::modifyPassConfig(MaterializationResponsibility &MR,86 LinkGraph &G,87 PassConfiguration &Config) {88 Config.PostFixupPasses.push_back([this, MR = &MR](LinkGraph &G) {89 // the object file is generated but not linked yet90 auto Batch = getMethodBatch(G, EmitDebugInfo);91 if (Batch.Methods.empty()) {92 return Error::success();93 }94 {95 std::lock_guard<std::mutex> Lock(PluginMutex);96 uint64_t Allocated = Batch.Methods.size();97 uint64_t Start = NextMethodID;98 NextMethodID += Allocated;99 for (size_t i = Start; i < NextMethodID; ++i) {100 Batch.Methods[i - Start].MethodID = i;101 }102 this->PendingMethodIDs[MR] = {Start, Allocated};103 }104 G.allocActions().push_back(105 {cantFail(shared::WrapperFunctionCall::Create<106 shared::SPSArgList<shared::SPSVTuneMethodBatch>>(107 RegisterVTuneImplAddr, Batch)),108 {}});109 return Error::success();110 });111}112 113Error VTuneSupportPlugin::notifyEmitted(MaterializationResponsibility &MR) {114 if (auto Err = MR.withResourceKeyDo([this, MR = &MR](ResourceKey K) {115 std::lock_guard<std::mutex> Lock(PluginMutex);116 auto I = PendingMethodIDs.find(MR);117 if (I == PendingMethodIDs.end())118 return;119 120 LoadedMethodIDs[K].push_back(I->second);121 PendingMethodIDs.erase(I);122 })) {123 return Err;124 }125 return Error::success();126}127 128Error VTuneSupportPlugin::notifyFailed(MaterializationResponsibility &MR) {129 std::lock_guard<std::mutex> Lock(PluginMutex);130 PendingMethodIDs.erase(&MR);131 return Error::success();132}133 134Error VTuneSupportPlugin::notifyRemovingResources(JITDylib &JD, ResourceKey K) {135 // Unregistration not required if not provided136 if (!UnregisterVTuneImplAddr) {137 return Error::success();138 }139 VTuneUnloadedMethodIDs UnloadedIDs;140 {141 std::lock_guard<std::mutex> Lock(PluginMutex);142 auto I = LoadedMethodIDs.find(K);143 if (I == LoadedMethodIDs.end())144 return Error::success();145 146 UnloadedIDs = std::move(I->second);147 LoadedMethodIDs.erase(I);148 }149 if (auto Err = EPC.callSPSWrapper<void(shared::SPSVTuneUnloadedMethodIDs)>(150 UnregisterVTuneImplAddr, UnloadedIDs))151 return Err;152 153 return Error::success();154}155 156void VTuneSupportPlugin::notifyTransferringResources(JITDylib &JD,157 ResourceKey DstKey,158 ResourceKey SrcKey) {159 std::lock_guard<std::mutex> Lock(PluginMutex);160 auto I = LoadedMethodIDs.find(SrcKey);161 if (I == LoadedMethodIDs.end())162 return;163 164 auto &Dest = LoadedMethodIDs[DstKey];165 llvm::append_range(Dest, I->second);166 LoadedMethodIDs.erase(SrcKey);167}168 169Expected<std::unique_ptr<VTuneSupportPlugin>>170VTuneSupportPlugin::Create(ExecutorProcessControl &EPC, JITDylib &JD,171 bool EmitDebugInfo, bool TestMode) {172 auto &ES = EPC.getExecutionSession();173 auto RegisterImplName =174 ES.intern(TestMode ? RegisterTestVTuneImplName : RegisterVTuneImplName);175 auto UnregisterImplName = ES.intern(UnregisterVTuneImplName);176 SymbolLookupSet SLS{RegisterImplName, UnregisterImplName};177 auto Res = ES.lookup(makeJITDylibSearchOrder({&JD}), std::move(SLS));178 if (!Res)179 return Res.takeError();180 ExecutorAddr RegisterImplAddr(181 Res->find(RegisterImplName)->second.getAddress());182 ExecutorAddr UnregisterImplAddr(183 Res->find(UnregisterImplName)->second.getAddress());184 return std::make_unique<VTuneSupportPlugin>(185 EPC, RegisterImplAddr, UnregisterImplAddr, EmitDebugInfo);186}187