Home | History | Annotate | Download | only in llvm-jitlistener
      1 //===-- llvm-jitlistener.cpp - Utility for testing MCJIT event listener ---===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This program is a used by lit tests to verify the MCJIT JITEventListener
     11 // interface.  It registers a mock JIT event listener, generates a module from
     12 // an input IR file and dumps the reported event information to stdout.
     13 //
     14 //===----------------------------------------------------------------------===//
     15 
     16 #include "llvm/IR/LLVMContext.h"
     17 #include "../../lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h"
     18 #include "llvm/ADT/Triple.h"
     19 #include "llvm/ExecutionEngine/JITEventListener.h"
     20 #include "llvm/ExecutionEngine/JITMemoryManager.h"
     21 #include "llvm/ExecutionEngine/MCJIT.h"
     22 #include "llvm/ExecutionEngine/ObjectImage.h"
     23 #include "llvm/IR/Module.h"
     24 #include "llvm/IRReader/IRReader.h"
     25 #include "llvm/Support/CommandLine.h"
     26 #include "llvm/Support/Host.h"
     27 #include "llvm/Support/ManagedStatic.h"
     28 #include "llvm/Support/MemoryBuffer.h"
     29 #include "llvm/Support/PrettyStackTrace.h"
     30 #include "llvm/Support/Signals.h"
     31 #include "llvm/Support/SourceMgr.h"
     32 #include "llvm/Support/TargetSelect.h"
     33 #include <string>
     34 
     35 using namespace llvm;
     36 
     37 namespace {
     38 
     39 typedef std::vector<std::pair<std::string, unsigned int> > SourceLocations;
     40 typedef std::map<uint64_t, SourceLocations> NativeCodeMap;
     41 
     42 NativeCodeMap  ReportedDebugFuncs;
     43 
     44 int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) {
     45   switch (EventType) {
     46     case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: {
     47       if (!EventSpecificData) {
     48         errs() <<
     49           "Error: The JIT event listener did not provide a event data.";
     50         return -1;
     51       }
     52       iJIT_Method_Load* msg = static_cast<iJIT_Method_Load*>(EventSpecificData);
     53 
     54       ReportedDebugFuncs[msg->method_id];
     55 
     56       outs() << "Method load [" << msg->method_id << "]: " << msg->method_name
     57              << ", Size = " << msg->method_size << "\n";
     58 
     59       for(unsigned int i = 0; i < msg->line_number_size; ++i) {
     60         if (!msg->line_number_table) {
     61           errs() << "A function with a non-zero line count had no line table.";
     62           return -1;
     63         }
     64         std::pair<std::string, unsigned int> loc(
     65           std::string(msg->source_file_name),
     66           msg->line_number_table[i].LineNumber);
     67         ReportedDebugFuncs[msg->method_id].push_back(loc);
     68         outs() << "  Line info @ " << msg->line_number_table[i].Offset
     69                << ": " << msg->source_file_name
     70                << ", line " << msg->line_number_table[i].LineNumber << "\n";
     71       }
     72       outs() << "\n";
     73     }
     74     break;
     75     case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: {
     76       if (!EventSpecificData) {
     77         errs() <<
     78           "Error: The JIT event listener did not provide a event data.";
     79         return -1;
     80       }
     81       unsigned int UnloadId
     82         = *reinterpret_cast<unsigned int*>(EventSpecificData);
     83       assert(1 == ReportedDebugFuncs.erase(UnloadId));
     84       outs() << "Method unload [" << UnloadId << "]\n";
     85     }
     86     break;
     87     default:
     88       break;
     89   }
     90   return 0;
     91 }
     92 
     93 iJIT_IsProfilingActiveFlags IsProfilingActive(void) {
     94   // for testing, pretend we have an Intel Parallel Amplifier XE 2011
     95   // instance attached
     96   return iJIT_SAMPLING_ON;
     97 }
     98 
     99 unsigned int GetNewMethodID(void) {
    100   static unsigned int id = 0;
    101   return ++id;
    102 }
    103 
    104 class JitEventListenerTest {
    105 protected:
    106   void InitEE(const std::string &IRFile) {
    107     LLVMContext &Context = getGlobalContext();
    108 
    109     // If we have a native target, initialize it to ensure it is linked in and
    110     // usable by the JIT.
    111     InitializeNativeTarget();
    112     InitializeNativeTargetAsmPrinter();
    113 
    114     // Parse the bitcode...
    115     SMDiagnostic Err;
    116     TheModule = ParseIRFile(IRFile, Err, Context);
    117     if (!TheModule) {
    118       errs() << Err.getMessage();
    119       return;
    120     }
    121 
    122     // FIXME: This is using the default legacy JITMemoryManager because it
    123     // supports poison memory.  At some point, we'll need to update this to
    124     // use an MCJIT-specific memory manager.  It might be nice to have the
    125     // poison memory option there too.
    126     JITMemoryManager *MemMgr = JITMemoryManager::CreateDefaultMemManager();
    127     if (!MemMgr) {
    128       errs() << "Unable to create memory manager.";
    129       return;
    130     }
    131 
    132     // Tell the memory manager to poison freed memory so that accessing freed
    133     // memory is more easily tested.
    134     MemMgr->setPoisonMemory(true);
    135 
    136     // Override the triple to generate ELF on Windows since that's supported
    137     Triple Tuple(TheModule->getTargetTriple());
    138     if (Tuple.getTriple().empty())
    139       Tuple.setTriple(sys::getProcessTriple());
    140 
    141     if (Tuple.isOSWindows() && !Tuple.isOSBinFormatELF()) {
    142       Tuple.setObjectFormat(Triple::ELF);
    143       TheModule->setTargetTriple(Tuple.getTriple());
    144     }
    145 
    146     // Compile the IR
    147     std::string Error;
    148     TheJIT.reset(EngineBuilder(TheModule)
    149       .setEngineKind(EngineKind::JIT)
    150       .setErrorStr(&Error)
    151       .setJITMemoryManager(MemMgr)
    152       .setUseMCJIT(true)
    153       .create());
    154     if (Error.empty() == false)
    155       errs() << Error;
    156   }
    157 
    158   void DestroyEE() {
    159     TheJIT.reset();
    160   }
    161 
    162   LLVMContext Context; // Global ownership
    163   Module *TheModule; // Owned by ExecutionEngine.
    164   JITMemoryManager *JMM; // Owned by ExecutionEngine.
    165   std::unique_ptr<ExecutionEngine> TheJIT;
    166 
    167 public:
    168   void ProcessInput(const std::string &Filename) {
    169     InitEE(Filename);
    170 
    171     std::unique_ptr<llvm::JITEventListener> Listener(
    172         JITEventListener::createIntelJITEventListener(new IntelJITEventsWrapper(
    173             NotifyEvent, 0, IsProfilingActive, 0, 0, GetNewMethodID)));
    174 
    175     TheJIT->RegisterJITEventListener(Listener.get());
    176 
    177     TheJIT->finalizeObject();
    178 
    179     // Destroy the JIT engine instead of unregistering to get unload events.
    180     DestroyEE();
    181   }
    182 };
    183 
    184 
    185 
    186 } // end anonymous namespace
    187 
    188 static cl::opt<std::string>
    189 InputFilename(cl::Positional, cl::desc("<input IR file>"),
    190                cl::Required);
    191 
    192 int main(int argc, char **argv) {
    193   // Print a stack trace if we signal out.
    194   sys::PrintStackTraceOnErrorSignal();
    195   PrettyStackTraceProgram X(argc, argv);
    196   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
    197 
    198   cl::ParseCommandLineOptions(argc, argv, "llvm jit event listener test utility\n");
    199 
    200   JitEventListenerTest Test;
    201 
    202   Test.ProcessInput(InputFilename);
    203 
    204   return 0;
    205 }
    206