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 "../../lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h"
     17 #include "llvm/ADT/Triple.h"
     18 #include "llvm/ExecutionEngine/JITEventListener.h"
     19 #include "llvm/ExecutionEngine/MCJIT.h"
     20 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
     21 #include "llvm/IR/LLVMContext.h"
     22 #include "llvm/IR/Module.h"
     23 #include "llvm/IRReader/IRReader.h"
     24 #include "llvm/Support/CommandLine.h"
     25 #include "llvm/Support/Debug.h"
     26 #include "llvm/Support/Host.h"
     27 #include "llvm/Support/InitLLVM.h"
     28 #include "llvm/Support/MemoryBuffer.h"
     29 #include "llvm/Support/SourceMgr.h"
     30 #include "llvm/Support/TargetSelect.h"
     31 #include "llvm/Support/raw_ostream.h"
     32 #include <string>
     33 
     34 using namespace llvm;
     35 
     36 namespace {
     37 
     38 typedef std::vector<std::pair<std::string, unsigned int> > SourceLocations;
     39 typedef std::map<uint64_t, SourceLocations> NativeCodeMap;
     40 
     41 NativeCodeMap  ReportedDebugFuncs;
     42 
     43 int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) {
     44   switch (EventType) {
     45     case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: {
     46       if (!EventSpecificData) {
     47         errs() <<
     48           "Error: The JIT event listener did not provide a event data.";
     49         return -1;
     50       }
     51       iJIT_Method_Load* msg = static_cast<iJIT_Method_Load*>(EventSpecificData);
     52 
     53       ReportedDebugFuncs[msg->method_id];
     54 
     55       outs() << "Method load [" << msg->method_id << "]: " << msg->method_name
     56              << ", Size = " << msg->method_size << "\n";
     57 
     58       for(unsigned int i = 0; i < msg->line_number_size; ++i) {
     59         if (!msg->line_number_table) {
     60           errs() << "A function with a non-zero line count had no line table.";
     61           return -1;
     62         }
     63         std::pair<std::string, unsigned int> loc(
     64           std::string(msg->source_file_name),
     65           msg->line_number_table[i].LineNumber);
     66         ReportedDebugFuncs[msg->method_id].push_back(loc);
     67         outs() << "  Line info @ " << msg->line_number_table[i].Offset
     68                << ": " << msg->source_file_name
     69                << ", line " << msg->line_number_table[i].LineNumber << "\n";
     70       }
     71       outs() << "\n";
     72     }
     73     break;
     74     case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: {
     75       if (!EventSpecificData) {
     76         errs() <<
     77           "Error: The JIT event listener did not provide a event data.";
     78         return -1;
     79       }
     80       unsigned int UnloadId
     81         = *reinterpret_cast<unsigned int*>(EventSpecificData);
     82       assert(1 == ReportedDebugFuncs.erase(UnloadId));
     83       outs() << "Method unload [" << UnloadId << "]\n";
     84     }
     85     break;
     86     default:
     87       break;
     88   }
     89   return 0;
     90 }
     91 
     92 iJIT_IsProfilingActiveFlags IsProfilingActive(void) {
     93   // for testing, pretend we have an Intel Parallel Amplifier XE 2011
     94   // instance attached
     95   return iJIT_SAMPLING_ON;
     96 }
     97 
     98 unsigned int GetNewMethodID(void) {
     99   static unsigned int id = 0;
    100   return ++id;
    101 }
    102 
    103 class JitEventListenerTest {
    104 protected:
    105   void InitEE(const std::string &IRFile) {
    106     // If we have a native target, initialize it to ensure it is linked in and
    107     // usable by the JIT.
    108     InitializeNativeTarget();
    109     InitializeNativeTargetAsmPrinter();
    110 
    111     // Parse the bitcode...
    112     SMDiagnostic Err;
    113     std::unique_ptr<Module> TheModule(parseIRFile(IRFile, Err, Context));
    114     if (!TheModule) {
    115       errs() << Err.getMessage();
    116       return;
    117     }
    118 
    119     RTDyldMemoryManager *MemMgr = new SectionMemoryManager();
    120     if (!MemMgr) {
    121       errs() << "Unable to create memory manager.";
    122       return;
    123     }
    124 
    125     // Override the triple to generate ELF on Windows since that's supported
    126     Triple Tuple(TheModule->getTargetTriple());
    127     if (Tuple.getTriple().empty())
    128       Tuple.setTriple(sys::getProcessTriple());
    129 
    130     if (Tuple.isOSWindows() && !Tuple.isOSBinFormatELF()) {
    131       Tuple.setObjectFormat(Triple::ELF);
    132       TheModule->setTargetTriple(Tuple.getTriple());
    133     }
    134 
    135     // Compile the IR
    136     std::string Error;
    137     TheJIT.reset(EngineBuilder(std::move(TheModule))
    138       .setEngineKind(EngineKind::JIT)
    139       .setErrorStr(&Error)
    140       .setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager>(MemMgr))
    141       .create());
    142     if (Error.empty() == false)
    143       errs() << Error;
    144   }
    145 
    146   void DestroyEE() {
    147     TheJIT.reset();
    148   }
    149 
    150   LLVMContext Context; // Global ownership
    151   std::unique_ptr<ExecutionEngine> TheJIT;
    152 
    153 public:
    154   void ProcessInput(const std::string &Filename) {
    155     InitEE(Filename);
    156 
    157     std::unique_ptr<llvm::JITEventListener> Listener(
    158         JITEventListener::createIntelJITEventListener(new IntelJITEventsWrapper(
    159             NotifyEvent, 0, IsProfilingActive, 0, 0, GetNewMethodID)));
    160 
    161     TheJIT->RegisterJITEventListener(Listener.get());
    162 
    163     TheJIT->finalizeObject();
    164 
    165     // Destroy the JIT engine instead of unregistering to get unload events.
    166     DestroyEE();
    167   }
    168 };
    169 
    170 
    171 
    172 } // end anonymous namespace
    173 
    174 static cl::opt<std::string>
    175 InputFilename(cl::Positional, cl::desc("<input IR file>"),
    176                cl::Required);
    177 
    178 int main(int argc, char **argv) {
    179   InitLLVM X(argc, argv);
    180   cl::ParseCommandLineOptions(argc, argv, "llvm jit event listener test utility\n");
    181 
    182   JitEventListenerTest Test;
    183   Test.ProcessInput(InputFilename);
    184   return 0;
    185 }
    186