xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.cpp (revision 2ccf7ed277df28651b94bbee9fccefdf22fb074f)
100f41216SHongyu Chen //===--- VTuneSupportPlugin.cpp -- Support for VTune profiler --*- 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 // Handles support for registering code with VIntel Tune's Amplfiier JIT API.
1000f41216SHongyu Chen //
1100f41216SHongyu Chen //===----------------------------------------------------------------------===//
1200f41216SHongyu Chen #include "llvm/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.h"
1300f41216SHongyu Chen #include "llvm/DebugInfo/DWARF/DWARFContext.h"
1400f41216SHongyu Chen #include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h"
1500f41216SHongyu Chen 
1600f41216SHongyu Chen using namespace llvm;
1700f41216SHongyu Chen using namespace llvm::orc;
1800f41216SHongyu Chen using namespace llvm::jitlink;
1900f41216SHongyu Chen 
2000f41216SHongyu Chen static constexpr StringRef RegisterVTuneImplName = "llvm_orc_registerVTuneImpl";
2100f41216SHongyu Chen static constexpr StringRef UnregisterVTuneImplName =
2200f41216SHongyu Chen     "llvm_orc_unregisterVTuneImpl";
2300f41216SHongyu Chen static constexpr StringRef RegisterTestVTuneImplName =
2400f41216SHongyu Chen     "llvm_orc_test_registerVTuneImpl";
2500f41216SHongyu Chen 
2600f41216SHongyu Chen static VTuneMethodBatch getMethodBatch(LinkGraph &G, bool EmitDebugInfo) {
2700f41216SHongyu Chen   VTuneMethodBatch Batch;
2800f41216SHongyu Chen   std::unique_ptr<DWARFContext> DC;
2900f41216SHongyu Chen   StringMap<std::unique_ptr<MemoryBuffer>> DCBacking;
3000f41216SHongyu Chen   if (EmitDebugInfo) {
3100f41216SHongyu Chen     auto EDC = createDWARFContext(G);
3200f41216SHongyu Chen     if (!EDC) {
3300f41216SHongyu Chen       EmitDebugInfo = false;
3400f41216SHongyu Chen     } else {
3500f41216SHongyu Chen       DC = std::move(EDC->first);
3600f41216SHongyu Chen       DCBacking = std::move(EDC->second);
3700f41216SHongyu Chen     }
3800f41216SHongyu Chen   }
3900f41216SHongyu Chen 
4000f41216SHongyu Chen   auto GetStringIdx = [Deduplicator = StringMap<uint32_t>(),
4100f41216SHongyu Chen                        &Batch](StringRef S) mutable {
42ede866d7SKazu Hirata     auto [I, Inserted] = Deduplicator.try_emplace(S);
43ede866d7SKazu Hirata     if (Inserted) {
4400f41216SHongyu Chen       Batch.Strings.push_back(S.str());
45ede866d7SKazu Hirata       I->second = Batch.Strings.size();
46ede866d7SKazu Hirata     }
47ede866d7SKazu Hirata     return I->second;
4800f41216SHongyu Chen   };
4900f41216SHongyu Chen   for (auto Sym : G.defined_symbols()) {
5000f41216SHongyu Chen     if (!Sym->isCallable())
5100f41216SHongyu Chen       continue;
5200f41216SHongyu Chen 
5300f41216SHongyu Chen     Batch.Methods.push_back(VTuneMethodInfo());
5400f41216SHongyu Chen     auto &Method = Batch.Methods.back();
5500f41216SHongyu Chen     Method.MethodID = 0;
5600f41216SHongyu Chen     Method.ParentMI = 0;
5700f41216SHongyu Chen     Method.LoadAddr = Sym->getAddress();
5800f41216SHongyu Chen     Method.LoadSize = Sym->getSize();
59*2ccf7ed2SJared Wyles     Method.NameSI = GetStringIdx(*Sym->getName());
6000f41216SHongyu Chen     Method.ClassFileSI = 0;
6100f41216SHongyu Chen     Method.SourceFileSI = 0;
6200f41216SHongyu Chen 
6300f41216SHongyu Chen     if (!EmitDebugInfo)
6400f41216SHongyu Chen       continue;
6500f41216SHongyu Chen 
6600f41216SHongyu Chen     auto &Section = Sym->getBlock().getSection();
6700f41216SHongyu Chen     auto Addr = Sym->getAddress();
6800f41216SHongyu Chen     auto SAddr =
6900f41216SHongyu Chen         object::SectionedAddress{Addr.getValue(), Section.getOrdinal()};
7000f41216SHongyu Chen     DILineInfoTable LinesInfo = DC->getLineInfoForAddressRange(
7100f41216SHongyu Chen         SAddr, Sym->getSize(),
7200f41216SHongyu Chen         DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath);
7300f41216SHongyu Chen     Method.SourceFileSI = Batch.Strings.size();
7400f41216SHongyu Chen     Batch.Strings.push_back(DC->getLineInfoForAddress(SAddr).FileName);
7500f41216SHongyu Chen     for (auto &LInfo : LinesInfo) {
7600f41216SHongyu Chen       Method.LineTable.push_back(
7700f41216SHongyu Chen           std::pair<unsigned, unsigned>{/*unsigned*/ Sym->getOffset(),
7800f41216SHongyu Chen                                         /*DILineInfo*/ LInfo.second.Line});
7900f41216SHongyu Chen     }
8000f41216SHongyu Chen   }
8100f41216SHongyu Chen   return Batch;
8200f41216SHongyu Chen }
8300f41216SHongyu Chen 
8400f41216SHongyu Chen void VTuneSupportPlugin::modifyPassConfig(MaterializationResponsibility &MR,
8500f41216SHongyu Chen                                           LinkGraph &G,
8600f41216SHongyu Chen                                           PassConfiguration &Config) {
8700f41216SHongyu Chen   Config.PostFixupPasses.push_back([this, MR = &MR](LinkGraph &G) {
8800f41216SHongyu Chen     // the object file is generated but not linked yet
8900f41216SHongyu Chen     auto Batch = getMethodBatch(G, EmitDebugInfo);
9000f41216SHongyu Chen     if (Batch.Methods.empty()) {
9100f41216SHongyu Chen       return Error::success();
9200f41216SHongyu Chen     }
9300f41216SHongyu Chen     {
9400f41216SHongyu Chen       std::lock_guard<std::mutex> Lock(PluginMutex);
9500f41216SHongyu Chen       uint64_t Allocated = Batch.Methods.size();
9600f41216SHongyu Chen       uint64_t Start = NextMethodID;
9700f41216SHongyu Chen       NextMethodID += Allocated;
9800f41216SHongyu Chen       for (size_t i = Start; i < NextMethodID; ++i) {
9900f41216SHongyu Chen         Batch.Methods[i - Start].MethodID = i;
10000f41216SHongyu Chen       }
10100f41216SHongyu Chen       this->PendingMethodIDs[MR] = {Start, Allocated};
10200f41216SHongyu Chen     }
10300f41216SHongyu Chen     G.allocActions().push_back(
10400f41216SHongyu Chen         {cantFail(shared::WrapperFunctionCall::Create<
10500f41216SHongyu Chen                   shared::SPSArgList<shared::SPSVTuneMethodBatch>>(
10600f41216SHongyu Chen              RegisterVTuneImplAddr, Batch)),
10700f41216SHongyu Chen          {}});
10800f41216SHongyu Chen     return Error::success();
10900f41216SHongyu Chen   });
11000f41216SHongyu Chen }
11100f41216SHongyu Chen 
11200f41216SHongyu Chen Error VTuneSupportPlugin::notifyEmitted(MaterializationResponsibility &MR) {
11300f41216SHongyu Chen   if (auto Err = MR.withResourceKeyDo([this, MR = &MR](ResourceKey K) {
11400f41216SHongyu Chen         std::lock_guard<std::mutex> Lock(PluginMutex);
11500f41216SHongyu Chen         auto I = PendingMethodIDs.find(MR);
11600f41216SHongyu Chen         if (I == PendingMethodIDs.end())
11700f41216SHongyu Chen           return;
11800f41216SHongyu Chen 
11900f41216SHongyu Chen         LoadedMethodIDs[K].push_back(I->second);
12000f41216SHongyu Chen         PendingMethodIDs.erase(I);
12100f41216SHongyu Chen       })) {
12200f41216SHongyu Chen     return Err;
12300f41216SHongyu Chen   }
12400f41216SHongyu Chen   return Error::success();
12500f41216SHongyu Chen }
12600f41216SHongyu Chen 
12700f41216SHongyu Chen Error VTuneSupportPlugin::notifyFailed(MaterializationResponsibility &MR) {
12800f41216SHongyu Chen   std::lock_guard<std::mutex> Lock(PluginMutex);
12900f41216SHongyu Chen   PendingMethodIDs.erase(&MR);
13000f41216SHongyu Chen   return Error::success();
13100f41216SHongyu Chen }
13200f41216SHongyu Chen 
13300f41216SHongyu Chen Error VTuneSupportPlugin::notifyRemovingResources(JITDylib &JD, ResourceKey K) {
13400f41216SHongyu Chen   // Unregistration not required if not provided
13500f41216SHongyu Chen   if (!UnregisterVTuneImplAddr) {
13600f41216SHongyu Chen     return Error::success();
13700f41216SHongyu Chen   }
13800f41216SHongyu Chen   VTuneUnloadedMethodIDs UnloadedIDs;
13900f41216SHongyu Chen   {
14000f41216SHongyu Chen     std::lock_guard<std::mutex> Lock(PluginMutex);
14100f41216SHongyu Chen     auto I = LoadedMethodIDs.find(K);
14200f41216SHongyu Chen     if (I == LoadedMethodIDs.end())
14300f41216SHongyu Chen       return Error::success();
14400f41216SHongyu Chen 
14500f41216SHongyu Chen     UnloadedIDs = std::move(I->second);
14600f41216SHongyu Chen     LoadedMethodIDs.erase(I);
14700f41216SHongyu Chen   }
14800f41216SHongyu Chen   if (auto Err = EPC.callSPSWrapper<void(shared::SPSVTuneUnloadedMethodIDs)>(
14900f41216SHongyu Chen           UnregisterVTuneImplAddr, UnloadedIDs))
15000f41216SHongyu Chen     return Err;
15100f41216SHongyu Chen 
15200f41216SHongyu Chen   return Error::success();
15300f41216SHongyu Chen }
15400f41216SHongyu Chen 
15500f41216SHongyu Chen void VTuneSupportPlugin::notifyTransferringResources(JITDylib &JD,
15600f41216SHongyu Chen                                                      ResourceKey DstKey,
15700f41216SHongyu Chen                                                      ResourceKey SrcKey) {
15800f41216SHongyu Chen   std::lock_guard<std::mutex> Lock(PluginMutex);
15900f41216SHongyu Chen   auto I = LoadedMethodIDs.find(SrcKey);
16000f41216SHongyu Chen   if (I == LoadedMethodIDs.end())
16100f41216SHongyu Chen     return;
16200f41216SHongyu Chen 
16300f41216SHongyu Chen   auto &Dest = LoadedMethodIDs[DstKey];
16400f41216SHongyu Chen   Dest.insert(Dest.end(), I->second.begin(), I->second.end());
16500f41216SHongyu Chen   LoadedMethodIDs.erase(SrcKey);
16600f41216SHongyu Chen }
16700f41216SHongyu Chen 
16800f41216SHongyu Chen Expected<std::unique_ptr<VTuneSupportPlugin>>
16900f41216SHongyu Chen VTuneSupportPlugin::Create(ExecutorProcessControl &EPC, JITDylib &JD,
17000f41216SHongyu Chen                            bool EmitDebugInfo, bool TestMode) {
17100f41216SHongyu Chen   auto &ES = EPC.getExecutionSession();
17200f41216SHongyu Chen   auto RegisterImplName =
17300f41216SHongyu Chen       ES.intern(TestMode ? RegisterTestVTuneImplName : RegisterVTuneImplName);
17400f41216SHongyu Chen   auto UnregisterImplName = ES.intern(UnregisterVTuneImplName);
17500f41216SHongyu Chen   SymbolLookupSet SLS{RegisterImplName, UnregisterImplName};
17600f41216SHongyu Chen   auto Res = ES.lookup(makeJITDylibSearchOrder({&JD}), std::move(SLS));
17700f41216SHongyu Chen   if (!Res)
17800f41216SHongyu Chen     return Res.takeError();
17900f41216SHongyu Chen   ExecutorAddr RegisterImplAddr(
18000f41216SHongyu Chen       Res->find(RegisterImplName)->second.getAddress());
18100f41216SHongyu Chen   ExecutorAddr UnregisterImplAddr(
18200f41216SHongyu Chen       Res->find(UnregisterImplName)->second.getAddress());
18300f41216SHongyu Chen   return std::make_unique<VTuneSupportPlugin>(
18400f41216SHongyu Chen       EPC, RegisterImplAddr, UnregisterImplAddr, EmitDebugInfo);
18500f41216SHongyu Chen }
186