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-exception 6 // 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 16 using namespace llvm; 17 using namespace llvm::orc; 18 using namespace llvm::jitlink; 19 20 static constexpr StringRef RegisterVTuneImplName = "llvm_orc_registerVTuneImpl"; 21 static constexpr StringRef UnregisterVTuneImplName = 22 "llvm_orc_unregisterVTuneImpl"; 23 static constexpr StringRef RegisterTestVTuneImplName = 24 "llvm_orc_test_registerVTuneImpl"; 25 26 static 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 = Deduplicator.find(S); 43 if (I != Deduplicator.end()) 44 return I->second; 45 46 Batch.Strings.push_back(S.str()); 47 return Deduplicator[S] = Batch.Strings.size(); 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->getBlock().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(DC->getLineInfoForAddress(SAddr).FileName); 75 for (auto &LInfo : LinesInfo) { 76 Method.LineTable.push_back( 77 std::pair<unsigned, unsigned>{/*unsigned*/ Sym->getOffset(), 78 /*DILineInfo*/ LInfo.second.Line}); 79 } 80 } 81 return Batch; 82 } 83 84 void VTuneSupportPlugin::modifyPassConfig(MaterializationResponsibility &MR, 85 LinkGraph &G, 86 PassConfiguration &Config) { 87 Config.PostFixupPasses.push_back([this, MR = &MR](LinkGraph &G) { 88 // the object file is generated but not linked yet 89 auto Batch = getMethodBatch(G, EmitDebugInfo); 90 if (Batch.Methods.empty()) { 91 return Error::success(); 92 } 93 { 94 std::lock_guard<std::mutex> Lock(PluginMutex); 95 uint64_t Allocated = Batch.Methods.size(); 96 uint64_t Start = NextMethodID; 97 NextMethodID += Allocated; 98 for (size_t i = Start; i < NextMethodID; ++i) { 99 Batch.Methods[i - Start].MethodID = i; 100 } 101 this->PendingMethodIDs[MR] = {Start, Allocated}; 102 } 103 G.allocActions().push_back( 104 {cantFail(shared::WrapperFunctionCall::Create< 105 shared::SPSArgList<shared::SPSVTuneMethodBatch>>( 106 RegisterVTuneImplAddr, Batch)), 107 {}}); 108 return Error::success(); 109 }); 110 } 111 112 Error VTuneSupportPlugin::notifyEmitted(MaterializationResponsibility &MR) { 113 if (auto Err = MR.withResourceKeyDo([this, MR = &MR](ResourceKey K) { 114 std::lock_guard<std::mutex> Lock(PluginMutex); 115 auto I = PendingMethodIDs.find(MR); 116 if (I == PendingMethodIDs.end()) 117 return; 118 119 LoadedMethodIDs[K].push_back(I->second); 120 PendingMethodIDs.erase(I); 121 })) { 122 return Err; 123 } 124 return Error::success(); 125 } 126 127 Error VTuneSupportPlugin::notifyFailed(MaterializationResponsibility &MR) { 128 std::lock_guard<std::mutex> Lock(PluginMutex); 129 PendingMethodIDs.erase(&MR); 130 return Error::success(); 131 } 132 133 Error VTuneSupportPlugin::notifyRemovingResources(JITDylib &JD, ResourceKey K) { 134 // Unregistration not required if not provided 135 if (!UnregisterVTuneImplAddr) { 136 return Error::success(); 137 } 138 VTuneUnloadedMethodIDs UnloadedIDs; 139 { 140 std::lock_guard<std::mutex> Lock(PluginMutex); 141 auto I = LoadedMethodIDs.find(K); 142 if (I == LoadedMethodIDs.end()) 143 return Error::success(); 144 145 UnloadedIDs = std::move(I->second); 146 LoadedMethodIDs.erase(I); 147 } 148 if (auto Err = EPC.callSPSWrapper<void(shared::SPSVTuneUnloadedMethodIDs)>( 149 UnregisterVTuneImplAddr, UnloadedIDs)) 150 return Err; 151 152 return Error::success(); 153 } 154 155 void VTuneSupportPlugin::notifyTransferringResources(JITDylib &JD, 156 ResourceKey DstKey, 157 ResourceKey SrcKey) { 158 std::lock_guard<std::mutex> Lock(PluginMutex); 159 auto I = LoadedMethodIDs.find(SrcKey); 160 if (I == LoadedMethodIDs.end()) 161 return; 162 163 auto &Dest = LoadedMethodIDs[DstKey]; 164 Dest.insert(Dest.end(), I->second.begin(), I->second.end()); 165 LoadedMethodIDs.erase(SrcKey); 166 } 167 168 Expected<std::unique_ptr<VTuneSupportPlugin>> 169 VTuneSupportPlugin::Create(ExecutorProcessControl &EPC, JITDylib &JD, 170 bool EmitDebugInfo, bool TestMode) { 171 auto &ES = EPC.getExecutionSession(); 172 auto RegisterImplName = 173 ES.intern(TestMode ? RegisterTestVTuneImplName : RegisterVTuneImplName); 174 auto UnregisterImplName = ES.intern(UnregisterVTuneImplName); 175 SymbolLookupSet SLS{RegisterImplName, UnregisterImplName}; 176 auto Res = ES.lookup(makeJITDylibSearchOrder({&JD}), std::move(SLS)); 177 if (!Res) 178 return Res.takeError(); 179 ExecutorAddr RegisterImplAddr( 180 Res->find(RegisterImplName)->second.getAddress()); 181 ExecutorAddr UnregisterImplAddr( 182 Res->find(UnregisterImplName)->second.getAddress()); 183 return std::make_unique<VTuneSupportPlugin>( 184 EPC, RegisterImplAddr, UnregisterImplAddr, EmitDebugInfo); 185 } 186