aboutsummaryrefslogtreecommitdiff
path: root/tools/llvm-jitlistener
diff options
context:
space:
mode:
authorAndrew Kaylor <andrew.kaylor@intel.com>2012-11-21 20:38:26 +0000
committerAndrew Kaylor <andrew.kaylor@intel.com>2012-11-21 20:38:26 +0000
commit238f34a706a60bf9606d70122bac0f77265e3431 (patch)
tree45dc277c05eabb92433b19189e1614d79793bf86 /tools/llvm-jitlistener
parentd43e06de594e734513eb4e24193eb2dd5288c0c4 (diff)
Adding tests for the Intel JIT event listener's MCJIT support.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@168459 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvm-jitlistener')
-rw-r--r--tools/llvm-jitlistener/CMakeLists.txt20
-rw-r--r--tools/llvm-jitlistener/LLVMBuild.txt22
-rw-r--r--tools/llvm-jitlistener/Makefile27
-rw-r--r--tools/llvm-jitlistener/llvm-jitlistener.cpp207
4 files changed, 276 insertions, 0 deletions
diff --git a/tools/llvm-jitlistener/CMakeLists.txt b/tools/llvm-jitlistener/CMakeLists.txt
new file mode 100644
index 0000000000..57a4a0cbe1
--- /dev/null
+++ b/tools/llvm-jitlistener/CMakeLists.txt
@@ -0,0 +1,20 @@
+# This tool is excluded from the CMake build if Intel JIT events are disabled.
+
+link_directories( ${LLVM_INTEL_JITEVENTS_LIBDIR} )
+include_directories( ${LLVM_INTEL_JITEVENTS_INCDIR} )
+
+set(LLVM_LINK_COMPONENTS
+ asmparser
+ bitreader
+ inteljitevents
+ interpreter
+ jit
+ mcjit
+ nativecodegen
+ object
+ selectiondag
+ )
+
+add_llvm_tool(llvm-jitlistener
+ llvm-jitlistener.cpp
+ )
diff --git a/tools/llvm-jitlistener/LLVMBuild.txt b/tools/llvm-jitlistener/LLVMBuild.txt
new file mode 100644
index 0000000000..c436dd90f9
--- /dev/null
+++ b/tools/llvm-jitlistener/LLVMBuild.txt
@@ -0,0 +1,22 @@
+;===- ./tools/llvm-jitlistener/LLVMBuild.txt -------------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Tool
+name = llvm-jitlistener
+parent = Tools
+required_libraries = AsmParser BitReader Interpreter JIT MCJIT NativeCodeGen Object SelectionDAG Native
diff --git a/tools/llvm-jitlistener/Makefile b/tools/llvm-jitlistener/Makefile
new file mode 100644
index 0000000000..0971e6a252
--- /dev/null
+++ b/tools/llvm-jitlistener/Makefile
@@ -0,0 +1,27 @@
+##===- tools/llvm-jitlistener/Makefile ---------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL := ../..
+TOOLNAME := llvm-jitlistener
+
+include $(LEVEL)/Makefile.config
+
+LINK_COMPONENTS := mcjit jit interpreter nativecodegen bitreader asmparser selectiondag Object
+
+# If Intel JIT Events support is configured, link against the LLVM Intel JIT
+# Events interface library. If not, this tool will do nothing useful, but it
+# will build correctly.
+ifeq ($(USE_INTEL_JITEVENTS), 1)
+ LINK_COMPONENTS += inteljitevents
+endif
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS := 1
+
+include $(LLVM_SRC_ROOT)/Makefile.rules
diff --git a/tools/llvm-jitlistener/llvm-jitlistener.cpp b/tools/llvm-jitlistener/llvm-jitlistener.cpp
new file mode 100644
index 0000000000..2b05e66e98
--- /dev/null
+++ b/tools/llvm-jitlistener/llvm-jitlistener.cpp
@@ -0,0 +1,207 @@
+//===-- llvm-jitlistener.cpp - Utility for testing MCJIT event listener ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This program is a used by lit tests to verify the MCJIT JITEventListener
+// interface. It registers a mock JIT event listener, generates a module from
+// an input IR file and dumps the reported event information to stdout.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/Triple.h"
+#include "../../lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h"
+#include "llvm/ExecutionEngine/JITEventListener.h"
+#include "llvm/ExecutionEngine/JITMemoryManager.h"
+#include "llvm/ExecutionEngine/MCJIT.h"
+#include "llvm/ExecutionEngine/ObjectImage.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/IRReader.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetSelect.h"
+#include <string>
+
+using namespace llvm;
+
+namespace {
+
+typedef std::vector<std::pair<std::string, unsigned int> > SourceLocations;
+typedef std::map<uint64_t, SourceLocations> NativeCodeMap;
+
+NativeCodeMap ReportedDebugFuncs;
+
+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;
+}
+
+iJIT_IsProfilingActiveFlags IsProfilingActive(void) {
+ // for testing, pretend we have an Intel Parallel Amplifier XE 2011
+ // instance attached
+ return iJIT_SAMPLING_ON;
+}
+
+unsigned int GetNewMethodID(void) {
+ static unsigned int id = 0;
+ return ++id;
+}
+
+class JitEventListenerTest {
+protected:
+ void InitEE(const std::string &IRFile) {
+ LLVMContext &Context = getGlobalContext();
+
+ // If we have a native target, initialize it to ensure it is linked in and
+ // usable by the JIT.
+ InitializeNativeTarget();
+ InitializeNativeTargetAsmPrinter();
+
+ // Parse the bitcode...
+ SMDiagnostic Err;
+ TheModule = ParseIRFile(IRFile, Err, Context);
+ if (!TheModule) {
+ errs() << Err.getMessage();
+ return;
+ }
+
+ // FIXME: This is using the default legacy JITMemoryManager because it
+ // supports poison memory. At some point, we'll need to update this to
+ // use an MCJIT-specific memory manager. It might be nice to have the
+ // poison memory option there too.
+ JITMemoryManager *MemMgr = JITMemoryManager::CreateDefaultMemManager();
+ if (!MemMgr) {
+ errs() << "Unable to create memory manager.";
+ return;
+ }
+
+ // Tell the memory manager to poison freed memory so that accessing freed
+ // memory is more easily tested.
+ MemMgr->setPoisonMemory(true);
+
+ // Override the triple to generate ELF on Windows since that's supported
+ Triple Tuple(TheModule->getTargetTriple());
+ if (Tuple.getTriple().empty())
+ Tuple.setTriple(LLVM_HOSTTRIPLE);
+
+ if (Tuple.isOSWindows() && Triple::ELF != Tuple.getEnvironment()) {
+ Tuple.setEnvironment(Triple::ELF);
+ TheModule->setTargetTriple(Tuple.getTriple());
+ }
+
+ // Compile the IR
+ std::string Error;
+ TheJIT.reset(EngineBuilder(TheModule)
+ .setEngineKind(EngineKind::JIT)
+ .setErrorStr(&Error)
+ .setJITMemoryManager(MemMgr)
+ .setUseMCJIT(true)
+ .create());
+ if (Error.empty() == false)
+ errs() << Error;
+ }
+
+ void DestroyEE() {
+ TheJIT.reset();
+ }
+
+ LLVMContext Context; // Global ownership
+ Module *TheModule; // Owned by ExecutionEngine.
+ JITMemoryManager *JMM; // Owned by ExecutionEngine.
+ OwningPtr<ExecutionEngine> TheJIT;
+
+public:
+ void ProcessInput(const std::string &Filename) {
+ InitEE(Filename);
+
+ llvm::OwningPtr<llvm::JITEventListener> Listener(JITEventListener::createIntelJITEventListener(
+ new IntelJITEventsWrapper(NotifyEvent, 0,
+ IsProfilingActive, 0, 0,
+ GetNewMethodID)));
+
+ TheJIT->RegisterJITEventListener(Listener.get());
+
+ TheJIT->finalizeObject();
+
+ // Destroy the JIT engine instead of unregistering to get unload events.
+ DestroyEE();
+ }
+};
+
+
+
+} // end anonymous namespace
+
+static cl::opt<std::string>
+InputFilename(cl::Positional, cl::desc("<input IR file>"),
+ cl::Required);
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+ cl::ParseCommandLineOptions(argc, argv, "llvm jit event listener test utility\n");
+
+ JitEventListenerTest Test;
+
+ Test.ProcessInput(InputFilename);
+
+ return 0;
+}