| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| //===-- Implementation of memset_explicit ---------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "src/string/memset_explicit.h" | ||
| #include "src/__support/common.h" | ||
| #include "src/string/memory_utils/inline_memset.h" | ||
|
|
||
| namespace LIBC_NAMESPACE { | ||
|
|
||
| [[gnu::noinline]] LLVM_LIBC_FUNCTION(void *, memset_explicit, | ||
| (void *dst, int value, size_t count)) { | ||
| // Use the inline memset function to set the memory. | ||
| inline_memset(dst, static_cast<uint8_t>(value), count); | ||
| // avoid dead store elimination | ||
| // The asm itself should also be sufficient to behave as a compiler barrier. | ||
| asm("" : : "r"(dst) : "memory"); | ||
| return dst; | ||
| } | ||
|
|
||
| } // namespace LIBC_NAMESPACE |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| //===-- Implementation header for memset_explicit ---------------*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_LIBC_SRC_STRING_MEMSET_EXPLICIT_H | ||
| #define LLVM_LIBC_SRC_STRING_MEMSET_EXPLICIT_H | ||
|
|
||
| #include <stddef.h> // size_t | ||
|
|
||
| namespace LIBC_NAMESPACE { | ||
|
|
||
| [[gnu::noinline]] void *memset_explicit(void *ptr, int value, size_t count); | ||
|
|
||
| } // namespace LIBC_NAMESPACE | ||
|
|
||
| #endif // LLVM_LIBC_SRC_STRING_MEMSET_EXPLICIT_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| //===-- Unittests for memset_explicit -------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "memory_utils/memory_check_utils.h" | ||
| #include "src/string/memset_explicit.h" | ||
| #include "test/UnitTest/Test.h" | ||
|
|
||
| namespace LIBC_NAMESPACE { | ||
|
|
||
| // Apply the same tests as memset | ||
|
|
||
| static inline void Adaptor(cpp::span<char> p1, uint8_t value, size_t size) { | ||
| LIBC_NAMESPACE::memset_explicit(p1.begin(), value, size); | ||
| } | ||
|
|
||
| TEST(LlvmLibcmemsetExplicitTest, SizeSweep) { | ||
| static constexpr size_t kMaxSize = 400; | ||
| Buffer DstBuffer(kMaxSize); | ||
| for (size_t size = 0; size < kMaxSize; ++size) { | ||
| const char value = size % 10; | ||
| auto dst = DstBuffer.span().subspan(0, size); | ||
| ASSERT_TRUE((CheckMemset<Adaptor>(dst, value, size))); | ||
| } | ||
| } | ||
|
|
||
| } // namespace LIBC_NAMESPACE |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // REQUIRES: stdlib=apple-libc++ | ||
|
|
||
| // Test that using -pedantic-errors doesn't turn off availability annotations. | ||
| // This used to be the case because we used __has_extension(...) to enable the | ||
| // availability annotations, and -pedantic-errors changes the behavior of | ||
| // __has_extension(...) in an incompatible way. | ||
|
|
||
| // ADDITIONAL_COMPILE_FLAGS: -pedantic-errors | ||
|
|
||
| #include <__availability> | ||
|
|
||
| #if defined(_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS) | ||
| # error Availability annotations should be enabled on Apple platforms in the system configuration! | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| //===--- VTuneSupportPlugin.h -- Support for VTune profiler ---*- C++ -*---===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Handles support for registering code with VIntel Tune's Amplifier JIT API. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_EXECUTIONENGINE_ORC_DEBUGGING_VTUNESUPPORT_H | ||
| #define LLVM_EXECUTIONENGINE_ORC_DEBUGGING_VTUNESUPPORT_H | ||
|
|
||
| #include "llvm/ADT/DenseMap.h" | ||
| #include "llvm/ADT/SmallVector.h" | ||
| #include "llvm/ExecutionEngine/Orc/Core.h" | ||
| #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" | ||
| #include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h" | ||
| #include "llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h" | ||
|
|
||
| namespace llvm { | ||
|
|
||
| namespace orc { | ||
|
|
||
| class VTuneSupportPlugin : public ObjectLinkingLayer::Plugin { | ||
| public: | ||
| VTuneSupportPlugin(ExecutorProcessControl &EPC, ExecutorAddr RegisterImplAddr, | ||
| ExecutorAddr UnregisterImplAddr, bool EmitDebugInfo) | ||
| : EPC(EPC), RegisterVTuneImplAddr(RegisterImplAddr), | ||
| UnregisterVTuneImplAddr(UnregisterImplAddr), | ||
| EmitDebugInfo(EmitDebugInfo) {} | ||
|
|
||
| void modifyPassConfig(MaterializationResponsibility &MR, | ||
| jitlink::LinkGraph &G, | ||
| jitlink::PassConfiguration &Config) override; | ||
|
|
||
| Error notifyEmitted(MaterializationResponsibility &MR) override; | ||
| Error notifyFailed(MaterializationResponsibility &MR) override; | ||
| Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override; | ||
| void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, | ||
| ResourceKey SrcKey) override; | ||
|
|
||
| static Expected<std::unique_ptr<VTuneSupportPlugin>> | ||
| Create(ExecutorProcessControl &EPC, JITDylib &JD, bool EmitDebugInfo, | ||
| bool TestMode = false); | ||
|
|
||
| private: | ||
| ExecutorProcessControl &EPC; | ||
| ExecutorAddr RegisterVTuneImplAddr; | ||
| ExecutorAddr UnregisterVTuneImplAddr; | ||
| std::mutex PluginMutex; | ||
| uint64_t NextMethodID = 0; | ||
| DenseMap<MaterializationResponsibility *, std::pair<uint64_t, uint64_t>> | ||
| PendingMethodIDs; | ||
| DenseMap<ResourceKey, SmallVector<std::pair<uint64_t, uint64_t>>> | ||
| LoadedMethodIDs; | ||
| bool EmitDebugInfo; | ||
| }; | ||
|
|
||
| } // end namespace orc | ||
|
|
||
| } // end namespace llvm | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| //===-------------------- VTuneSharedStructs.h ------------------*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Structs and serialization to share VTune-related information | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_VTUNESHAREDSTRUCTS_H | ||
| #define LLVM_EXECUTIONENGINE_ORC_SHARED_VTUNESHAREDSTRUCTS_H | ||
|
|
||
| namespace llvm { | ||
| namespace orc { | ||
|
|
||
| using VTuneLineTable = std::vector<std::pair<unsigned, unsigned>>; | ||
|
|
||
| // SI = String Index, 1-indexed into the VTuneMethodBatch::Strings table. | ||
| // SI == 0 means replace with nullptr. | ||
|
|
||
| // MI = Method Index, 1-indexed into the VTuneMethodBatch::Methods table. | ||
| // MI == 0 means this is a parent method and was not inlined. | ||
|
|
||
| struct VTuneMethodInfo { | ||
| VTuneLineTable LineTable; | ||
| ExecutorAddr LoadAddr; | ||
| uint64_t LoadSize; | ||
| uint64_t MethodID; | ||
| uint32_t NameSI; | ||
| uint32_t ClassFileSI; | ||
| uint32_t SourceFileSI; | ||
| uint32_t ParentMI; | ||
| }; | ||
|
|
||
| using VTuneMethodTable = std::vector<VTuneMethodInfo>; | ||
| using VTuneStringTable = std::vector<std::string>; | ||
|
|
||
| struct VTuneMethodBatch { | ||
| VTuneMethodTable Methods; | ||
| VTuneStringTable Strings; | ||
| }; | ||
|
|
||
| using VTuneUnloadedMethodIDs = SmallVector<std::pair<uint64_t, uint64_t>>; | ||
|
|
||
| namespace shared { | ||
|
|
||
| using SPSVTuneLineTable = SPSSequence<SPSTuple<uint32_t, uint32_t>>; | ||
| using SPSVTuneMethodInfo = | ||
| SPSTuple<SPSVTuneLineTable, SPSExecutorAddr, uint64_t, uint64_t, uint32_t, | ||
| uint32_t, uint32_t, uint32_t>; | ||
| using SPSVTuneMethodTable = SPSSequence<SPSVTuneMethodInfo>; | ||
| using SPSVTuneStringTable = SPSSequence<SPSString>; | ||
| using SPSVTuneMethodBatch = SPSTuple<SPSVTuneMethodTable, SPSVTuneStringTable>; | ||
| using SPSVTuneUnloadedMethodIDs = SPSSequence<SPSTuple<uint64_t, uint64_t>>; | ||
|
|
||
| template <> class SPSSerializationTraits<SPSVTuneMethodInfo, VTuneMethodInfo> { | ||
| public: | ||
| static size_t size(const VTuneMethodInfo &MI) { | ||
| return SPSVTuneMethodInfo::AsArgList::size( | ||
| MI.LineTable, MI.LoadAddr, MI.LoadSize, MI.MethodID, MI.NameSI, | ||
| MI.ClassFileSI, MI.SourceFileSI, MI.ParentMI); | ||
| } | ||
|
|
||
| static bool deserialize(SPSInputBuffer &IB, VTuneMethodInfo &MI) { | ||
| return SPSVTuneMethodInfo::AsArgList::deserialize( | ||
| IB, MI.LineTable, MI.LoadAddr, MI.LoadSize, MI.MethodID, MI.NameSI, | ||
| MI.ClassFileSI, MI.SourceFileSI, MI.ParentMI); | ||
| } | ||
|
|
||
| static bool serialize(SPSOutputBuffer &OB, const VTuneMethodInfo &MI) { | ||
| return SPSVTuneMethodInfo::AsArgList::serialize( | ||
| OB, MI.LineTable, MI.LoadAddr, MI.LoadSize, MI.MethodID, MI.NameSI, | ||
| MI.ClassFileSI, MI.SourceFileSI, MI.ParentMI); | ||
| } | ||
| }; | ||
|
|
||
| template <> | ||
| class SPSSerializationTraits<SPSVTuneMethodBatch, VTuneMethodBatch> { | ||
| public: | ||
| static size_t size(const VTuneMethodBatch &MB) { | ||
| return SPSVTuneMethodBatch::AsArgList::size(MB.Methods, MB.Strings); | ||
| } | ||
|
|
||
| static bool deserialize(SPSInputBuffer &IB, VTuneMethodBatch &MB) { | ||
| return SPSVTuneMethodBatch::AsArgList::deserialize(IB, MB.Methods, | ||
| MB.Strings); | ||
| } | ||
|
|
||
| static bool serialize(SPSOutputBuffer &OB, const VTuneMethodBatch &MB) { | ||
| return SPSVTuneMethodBatch::AsArgList::serialize(OB, MB.Methods, | ||
| MB.Strings); | ||
| } | ||
| }; | ||
|
|
||
| } // end namespace shared | ||
| } // end namespace orc | ||
| } // end namespace llvm | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
|
|
||
| //===------ JITLoaderVTune.h --- Register profiler objects ------*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Register objects for access by profilers via the perf JIT interface. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_JITLOADERVTUNE_H | ||
| #define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_JITLOADERVTUNE_H | ||
|
|
||
| #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h" | ||
| #include <cstdint> | ||
|
|
||
| extern "C" llvm::orc::shared::CWrapperFunctionResult | ||
| llvm_orc_registerVTuneImpl(const char *Data, uint64_t Size); | ||
|
|
||
| extern "C" llvm::orc::shared::CWrapperFunctionResult | ||
| llvm_orc_unregisterVTuneImpl(const char *Data, uint64_t Size); | ||
|
|
||
| extern "C" llvm::orc::shared::CWrapperFunctionResult | ||
| llvm_orc_test_registerVTuneImpl(const char *Data, uint64_t Size); | ||
|
|
||
| #endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_JITLOADERVTUNE_H | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,185 @@ | ||
| //===--- VTuneSupportPlugin.cpp -- Support for VTune profiler --*- C++ -*--===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Handles support for registering code with VIntel Tune's Amplfiier JIT API. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| #include "llvm/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.h" | ||
| #include "llvm/DebugInfo/DWARF/DWARFContext.h" | ||
| #include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h" | ||
|
|
||
| using namespace llvm; | ||
| using namespace llvm::orc; | ||
| using namespace llvm::jitlink; | ||
|
|
||
| static constexpr StringRef RegisterVTuneImplName = "llvm_orc_registerVTuneImpl"; | ||
| static constexpr StringRef UnregisterVTuneImplName = | ||
| "llvm_orc_unregisterVTuneImpl"; | ||
| static constexpr StringRef RegisterTestVTuneImplName = | ||
| "llvm_orc_test_registerVTuneImpl"; | ||
|
|
||
| static VTuneMethodBatch getMethodBatch(LinkGraph &G, bool EmitDebugInfo) { | ||
| VTuneMethodBatch Batch; | ||
| std::unique_ptr<DWARFContext> DC; | ||
| StringMap<std::unique_ptr<MemoryBuffer>> DCBacking; | ||
| if (EmitDebugInfo) { | ||
| auto EDC = createDWARFContext(G); | ||
| if (!EDC) { | ||
| EmitDebugInfo = false; | ||
| } else { | ||
| DC = std::move(EDC->first); | ||
| DCBacking = std::move(EDC->second); | ||
| } | ||
| } | ||
|
|
||
| auto GetStringIdx = [Deduplicator = StringMap<uint32_t>(), | ||
| &Batch](StringRef S) mutable { | ||
| auto I = Deduplicator.find(S); | ||
| if (I != Deduplicator.end()) | ||
| return I->second; | ||
|
|
||
| Batch.Strings.push_back(S.str()); | ||
| return Deduplicator[S] = Batch.Strings.size(); | ||
| }; | ||
| for (auto Sym : G.defined_symbols()) { | ||
| if (!Sym->isCallable()) | ||
| continue; | ||
|
|
||
| Batch.Methods.push_back(VTuneMethodInfo()); | ||
| auto &Method = Batch.Methods.back(); | ||
| Method.MethodID = 0; | ||
| Method.ParentMI = 0; | ||
| Method.LoadAddr = Sym->getAddress(); | ||
| Method.LoadSize = Sym->getSize(); | ||
| Method.NameSI = GetStringIdx(Sym->getName()); | ||
| Method.ClassFileSI = 0; | ||
| Method.SourceFileSI = 0; | ||
|
|
||
| if (!EmitDebugInfo) | ||
| continue; | ||
|
|
||
| auto &Section = Sym->getBlock().getSection(); | ||
| auto Addr = Sym->getAddress(); | ||
| auto SAddr = | ||
| object::SectionedAddress{Addr.getValue(), Section.getOrdinal()}; | ||
| DILineInfoTable LinesInfo = DC->getLineInfoForAddressRange( | ||
| SAddr, Sym->getSize(), | ||
| DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath); | ||
| Method.SourceFileSI = Batch.Strings.size(); | ||
| Batch.Strings.push_back(DC->getLineInfoForAddress(SAddr).FileName); | ||
| for (auto &LInfo : LinesInfo) { | ||
| Method.LineTable.push_back( | ||
| std::pair<unsigned, unsigned>{/*unsigned*/ Sym->getOffset(), | ||
| /*DILineInfo*/ LInfo.second.Line}); | ||
| } | ||
| } | ||
| return Batch; | ||
| } | ||
|
|
||
| void VTuneSupportPlugin::modifyPassConfig(MaterializationResponsibility &MR, | ||
| LinkGraph &G, | ||
| PassConfiguration &Config) { | ||
| Config.PostFixupPasses.push_back([this, MR = &MR](LinkGraph &G) { | ||
| // the object file is generated but not linked yet | ||
| auto Batch = getMethodBatch(G, EmitDebugInfo); | ||
| if (Batch.Methods.empty()) { | ||
| return Error::success(); | ||
| } | ||
| { | ||
| std::lock_guard<std::mutex> Lock(PluginMutex); | ||
| uint64_t Allocated = Batch.Methods.size(); | ||
| uint64_t Start = NextMethodID; | ||
| NextMethodID += Allocated; | ||
| for (size_t i = Start; i < NextMethodID; ++i) { | ||
| Batch.Methods[i - Start].MethodID = i; | ||
| } | ||
| this->PendingMethodIDs[MR] = {Start, Allocated}; | ||
| } | ||
| G.allocActions().push_back( | ||
| {cantFail(shared::WrapperFunctionCall::Create< | ||
| shared::SPSArgList<shared::SPSVTuneMethodBatch>>( | ||
| RegisterVTuneImplAddr, Batch)), | ||
| {}}); | ||
| return Error::success(); | ||
| }); | ||
| } | ||
|
|
||
| Error VTuneSupportPlugin::notifyEmitted(MaterializationResponsibility &MR) { | ||
| if (auto Err = MR.withResourceKeyDo([this, MR = &MR](ResourceKey K) { | ||
| std::lock_guard<std::mutex> Lock(PluginMutex); | ||
| auto I = PendingMethodIDs.find(MR); | ||
| if (I == PendingMethodIDs.end()) | ||
| return; | ||
|
|
||
| LoadedMethodIDs[K].push_back(I->second); | ||
| PendingMethodIDs.erase(I); | ||
| })) { | ||
| return Err; | ||
| } | ||
| return Error::success(); | ||
| } | ||
|
|
||
| Error VTuneSupportPlugin::notifyFailed(MaterializationResponsibility &MR) { | ||
| std::lock_guard<std::mutex> Lock(PluginMutex); | ||
| PendingMethodIDs.erase(&MR); | ||
| return Error::success(); | ||
| } | ||
|
|
||
| Error VTuneSupportPlugin::notifyRemovingResources(JITDylib &JD, ResourceKey K) { | ||
| // Unregistration not required if not provided | ||
| if (!UnregisterVTuneImplAddr) { | ||
| return Error::success(); | ||
| } | ||
| VTuneUnloadedMethodIDs UnloadedIDs; | ||
| { | ||
| std::lock_guard<std::mutex> Lock(PluginMutex); | ||
| auto I = LoadedMethodIDs.find(K); | ||
| if (I == LoadedMethodIDs.end()) | ||
| return Error::success(); | ||
|
|
||
| UnloadedIDs = std::move(I->second); | ||
| LoadedMethodIDs.erase(I); | ||
| } | ||
| if (auto Err = EPC.callSPSWrapper<void(shared::SPSVTuneUnloadedMethodIDs)>( | ||
| UnregisterVTuneImplAddr, UnloadedIDs)) | ||
| return Err; | ||
|
|
||
| return Error::success(); | ||
| } | ||
|
|
||
| void VTuneSupportPlugin::notifyTransferringResources(JITDylib &JD, | ||
| ResourceKey DstKey, | ||
| ResourceKey SrcKey) { | ||
| std::lock_guard<std::mutex> Lock(PluginMutex); | ||
| auto I = LoadedMethodIDs.find(SrcKey); | ||
| if (I == LoadedMethodIDs.end()) | ||
| return; | ||
|
|
||
| auto &Dest = LoadedMethodIDs[DstKey]; | ||
| Dest.insert(Dest.end(), I->second.begin(), I->second.end()); | ||
| LoadedMethodIDs.erase(SrcKey); | ||
| } | ||
|
|
||
| Expected<std::unique_ptr<VTuneSupportPlugin>> | ||
| VTuneSupportPlugin::Create(ExecutorProcessControl &EPC, JITDylib &JD, | ||
| bool EmitDebugInfo, bool TestMode) { | ||
| auto &ES = EPC.getExecutionSession(); | ||
| auto RegisterImplName = | ||
| ES.intern(TestMode ? RegisterTestVTuneImplName : RegisterVTuneImplName); | ||
| auto UnregisterImplName = ES.intern(UnregisterVTuneImplName); | ||
| SymbolLookupSet SLS{RegisterImplName, UnregisterImplName}; | ||
| auto Res = ES.lookup(makeJITDylibSearchOrder({&JD}), std::move(SLS)); | ||
| if (!Res) | ||
| return Res.takeError(); | ||
| ExecutorAddr RegisterImplAddr( | ||
| Res->find(RegisterImplName)->second.getAddress()); | ||
| ExecutorAddr UnregisterImplAddr( | ||
| Res->find(UnregisterImplName)->second.getAddress()); | ||
| return std::make_unique<VTuneSupportPlugin>( | ||
| EPC, RegisterImplAddr, UnregisterImplAddr, EmitDebugInfo); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,224 @@ | ||
| //===------- JITLoaderVTune.cpp - Register profiler objects -----*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Register objects for access by profilers via the VTune JIT interface. | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h" | ||
| #include "llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h" | ||
| #include <map> | ||
|
|
||
| #if LLVM_USE_INTEL_JITEVENTS | ||
| #include "IntelJITEventsWrapper.h" | ||
| #include "ittnotify.h" | ||
|
|
||
| using namespace llvm; | ||
| using namespace llvm::orc; | ||
|
|
||
| namespace { | ||
| class JITEventWrapper { | ||
| public: | ||
| static std::unique_ptr<IntelJITEventsWrapper> Wrapper; | ||
| }; | ||
| std::unique_ptr<IntelJITEventsWrapper> JITEventWrapper::Wrapper; | ||
| } // namespace | ||
|
|
||
| static Error registerJITLoaderVTuneRegisterImpl(const VTuneMethodBatch &MB) { | ||
| const size_t StringsSize = MB.Strings.size(); | ||
|
|
||
| for (const auto &MethodInfo : MB.Methods) { | ||
| iJIT_Method_Load MethodMessage; | ||
| memset(&MethodMessage, 0, sizeof(iJIT_Method_Load)); | ||
|
|
||
| MethodMessage.method_id = MethodInfo.MethodID; | ||
| if (MethodInfo.NameSI != 0 && MethodInfo.NameSI < StringsSize) { | ||
| MethodMessage.method_name = | ||
| const_cast<char *>(MB.Strings.at(MethodInfo.NameSI).data()); | ||
| } else { | ||
| MethodMessage.method_name = NULL; | ||
| } | ||
| if (MethodInfo.ClassFileSI != 0 && MethodInfo.ClassFileSI < StringsSize) { | ||
| MethodMessage.class_file_name = | ||
| const_cast<char *>(MB.Strings.at(MethodInfo.ClassFileSI).data()); | ||
| } else { | ||
| MethodMessage.class_file_name = NULL; | ||
| } | ||
| if (MethodInfo.SourceFileSI != 0 && MethodInfo.SourceFileSI < StringsSize) { | ||
| MethodMessage.source_file_name = | ||
| const_cast<char *>(MB.Strings.at(MethodInfo.SourceFileSI).data()); | ||
| } else { | ||
| MethodMessage.source_file_name = NULL; | ||
| } | ||
|
|
||
| MethodMessage.method_load_address = MethodInfo.LoadAddr.toPtr<void *>(); | ||
| MethodMessage.method_size = MethodInfo.LoadSize; | ||
| MethodMessage.class_id = 0; | ||
|
|
||
| MethodMessage.user_data = NULL; | ||
| MethodMessage.user_data_size = 0; | ||
| MethodMessage.env = iJDE_JittingAPI; | ||
|
|
||
| std::vector<LineNumberInfo> LineInfo; | ||
| for (const auto &LInfo : MethodInfo.LineTable) { | ||
| LineInfo.push_back(LineNumberInfo{LInfo.first, LInfo.second}); | ||
| } | ||
|
|
||
| if (LineInfo.size() == 0) { | ||
| MethodMessage.line_number_size = 0; | ||
| MethodMessage.line_number_table = 0; | ||
| } else { | ||
| MethodMessage.line_number_size = LineInfo.size(); | ||
| MethodMessage.line_number_table = &*LineInfo.begin(); | ||
| } | ||
| JITEventWrapper::Wrapper->iJIT_NotifyEvent( | ||
| iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &MethodMessage); | ||
| } | ||
|
|
||
| return Error::success(); | ||
| } | ||
|
|
||
| static void registerJITLoaderVTuneUnregisterImpl( | ||
| const std::vector<std::pair<uint64_t, uint64_t>> &UM) { | ||
| for (auto &Method : UM) { | ||
| JITEventWrapper::Wrapper->iJIT_NotifyEvent( | ||
| iJVM_EVENT_TYPE_METHOD_UNLOAD_START, | ||
| const_cast<unsigned long *>(&Method.first)); | ||
| } | ||
| } | ||
|
|
||
| extern "C" llvm::orc::shared::CWrapperFunctionResult | ||
| llvm_orc_registerVTuneImpl(const char *Data, uint64_t Size) { | ||
| using namespace orc::shared; | ||
| if (!JITEventWrapper::Wrapper) | ||
| JITEventWrapper::Wrapper.reset(new IntelJITEventsWrapper); | ||
|
|
||
| return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle( | ||
| Data, Size, registerJITLoaderVTuneRegisterImpl) | ||
| .release(); | ||
| } | ||
|
|
||
| extern "C" llvm::orc::shared::CWrapperFunctionResult | ||
| llvm_orc_unregisterVTuneImpl(const char *Data, uint64_t Size) { | ||
| using namespace orc::shared; | ||
| return WrapperFunction<void(SPSVTuneUnloadedMethodIDs)>::handle( | ||
| Data, Size, registerJITLoaderVTuneUnregisterImpl) | ||
| .release(); | ||
| } | ||
|
|
||
| // For Testing: following code comes from llvm-jitlistener.cpp in llvm tools | ||
| namespace { | ||
| using SourceLocations = std::vector<std::pair<std::string, unsigned int>>; | ||
| using NativeCodeMap = std::map<uint64_t, SourceLocations>; | ||
| NativeCodeMap ReportedDebugFuncs; | ||
| } // namespace | ||
|
|
||
| static int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) { | ||
| switch (EventType) { | ||
| case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: { | ||
| if (!EventSpecificData) { | ||
| errs() << "Error: The JIT event listener did not provide a event data."; | ||
| return -1; | ||
| } | ||
| iJIT_Method_Load *msg = static_cast<iJIT_Method_Load *>(EventSpecificData); | ||
|
|
||
| ReportedDebugFuncs[msg->method_id]; | ||
|
|
||
| outs() << "Method load [" << msg->method_id << "]: " << msg->method_name | ||
| << ", Size = " << msg->method_size << "\n"; | ||
|
|
||
| for (unsigned int i = 0; i < msg->line_number_size; ++i) { | ||
| if (!msg->line_number_table) { | ||
| errs() << "A function with a non-zero line count had no line table."; | ||
| return -1; | ||
| } | ||
| std::pair<std::string, unsigned int> loc( | ||
| std::string(msg->source_file_name), | ||
| msg->line_number_table[i].LineNumber); | ||
| ReportedDebugFuncs[msg->method_id].push_back(loc); | ||
| outs() << " Line info @ " << msg->line_number_table[i].Offset << ": " | ||
| << msg->source_file_name << ", line " | ||
| << msg->line_number_table[i].LineNumber << "\n"; | ||
| } | ||
| outs() << "\n"; | ||
| } break; | ||
| case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: { | ||
| if (!EventSpecificData) { | ||
| errs() << "Error: The JIT event listener did not provide a event data."; | ||
| return -1; | ||
| } | ||
| unsigned int UnloadId = | ||
| *reinterpret_cast<unsigned int *>(EventSpecificData); | ||
| assert(1 == ReportedDebugFuncs.erase(UnloadId)); | ||
| outs() << "Method unload [" << UnloadId << "]\n"; | ||
| } break; | ||
| default: | ||
| break; | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| static iJIT_IsProfilingActiveFlags IsProfilingActive(void) { | ||
| // for testing, pretend we have an Intel Parallel Amplifier XE 2011 | ||
| // instance attached | ||
| return iJIT_SAMPLING_ON; | ||
| } | ||
|
|
||
| static unsigned int GetNewMethodID(void) { | ||
| static unsigned int id = 0; | ||
| return ++id; | ||
| } | ||
|
|
||
| extern "C" llvm::orc::shared::CWrapperFunctionResult | ||
| llvm_orc_test_registerVTuneImpl(const char *Data, uint64_t Size) { | ||
| using namespace orc::shared; | ||
| JITEventWrapper::Wrapper.reset(new IntelJITEventsWrapper( | ||
| NotifyEvent, NULL, NULL, IsProfilingActive, 0, 0, GetNewMethodID)); | ||
| return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle( | ||
| Data, Size, registerJITLoaderVTuneRegisterImpl) | ||
| .release(); | ||
| } | ||
|
|
||
| #else | ||
|
|
||
| using namespace llvm; | ||
| using namespace llvm::orc; | ||
|
|
||
| static Error unsupportedBatch(const VTuneMethodBatch &MB) { | ||
| return llvm::make_error<StringError>("unsupported for Intel VTune", | ||
| inconvertibleErrorCode()); | ||
| } | ||
|
|
||
| static void unsuppported(const std::vector<std::pair<uint64_t, uint64_t>> &UM) { | ||
|
|
||
| } | ||
|
|
||
| extern "C" llvm::orc::shared::CWrapperFunctionResult | ||
| llvm_orc_registerVTuneImpl(const char *Data, uint64_t Size) { | ||
| using namespace orc::shared; | ||
| return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle( | ||
| Data, Size, unsupportedBatch) | ||
| .release(); | ||
| } | ||
|
|
||
| extern "C" llvm::orc::shared::CWrapperFunctionResult | ||
| llvm_orc_unregisterVTuneImpl(const char *Data, uint64_t Size) { | ||
| using namespace orc::shared; | ||
| return WrapperFunction<void(SPSVTuneUnloadedMethodIDs)>::handle(Data, Size, | ||
| unsuppported) | ||
| .release(); | ||
| } | ||
|
|
||
| extern "C" llvm::orc::shared::CWrapperFunctionResult | ||
| llvm_orc_test_registerVTuneImpl(const char *Data, uint64_t Size) { | ||
| using namespace orc::shared; | ||
| return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle( | ||
| Data, Size, unsupportedBatch) | ||
| .release(); | ||
| } | ||
|
|
||
| #endif |