]> git.proxmox.com Git - rustc.git/blob - src/llvm/tools/llvm-jitlistener/llvm-jitlistener.cpp
Imported Upstream version 1.0.0+dfsg1
[rustc.git] / src / llvm / tools / llvm-jitlistener / llvm-jitlistener.cpp
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/MCJIT.h"
21 #include "llvm/ExecutionEngine/SectionMemoryManager.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/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 std::unique_ptr<Module> TheModule(parseIRFile(IRFile, Err, Context));
117 if (!TheModule) {
118 errs() << Err.getMessage();
119 return;
120 }
121
122 RTDyldMemoryManager *MemMgr = new SectionMemoryManager();
123 if (!MemMgr) {
124 errs() << "Unable to create memory manager.";
125 return;
126 }
127
128 // Override the triple to generate ELF on Windows since that's supported
129 Triple Tuple(TheModule->getTargetTriple());
130 if (Tuple.getTriple().empty())
131 Tuple.setTriple(sys::getProcessTriple());
132
133 if (Tuple.isOSWindows() && !Tuple.isOSBinFormatELF()) {
134 Tuple.setObjectFormat(Triple::ELF);
135 TheModule->setTargetTriple(Tuple.getTriple());
136 }
137
138 // Compile the IR
139 std::string Error;
140 TheJIT.reset(EngineBuilder(std::move(TheModule))
141 .setEngineKind(EngineKind::JIT)
142 .setErrorStr(&Error)
143 .setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager>(MemMgr))
144 .create());
145 if (Error.empty() == false)
146 errs() << Error;
147 }
148
149 void DestroyEE() {
150 TheJIT.reset();
151 }
152
153 LLVMContext Context; // Global ownership
154 std::unique_ptr<ExecutionEngine> TheJIT;
155
156 public:
157 void ProcessInput(const std::string &Filename) {
158 InitEE(Filename);
159
160 std::unique_ptr<llvm::JITEventListener> Listener(
161 JITEventListener::createIntelJITEventListener(new IntelJITEventsWrapper(
162 NotifyEvent, 0, IsProfilingActive, 0, 0, GetNewMethodID)));
163
164 TheJIT->RegisterJITEventListener(Listener.get());
165
166 TheJIT->finalizeObject();
167
168 // Destroy the JIT engine instead of unregistering to get unload events.
169 DestroyEE();
170 }
171 };
172
173
174
175 } // end anonymous namespace
176
177 static cl::opt<std::string>
178 InputFilename(cl::Positional, cl::desc("<input IR file>"),
179 cl::Required);
180
181 int main(int argc, char **argv) {
182 // Print a stack trace if we signal out.
183 sys::PrintStackTraceOnErrorSignal();
184 PrettyStackTraceProgram X(argc, argv);
185 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
186
187 cl::ParseCommandLineOptions(argc, argv, "llvm jit event listener test utility\n");
188
189 JitEventListenerTest Test;
190
191 Test.ProcessInput(InputFilename);
192
193 return 0;
194 }