blob: a37224b1b1c0d7b11c07e169351ddeff5fea8422 [file] [log] [blame]
Chris Lattner92101ac2001-08-23 17:05:04 +00001//===-- UserInput.cpp - Interpreter Input Loop support --------------------===//
2//
3// This file implements the interpreter Input I/O loop.
4//
5//===----------------------------------------------------------------------===//
6
7#include "Interpreter.h"
Chris Lattner2e42d3a2001-10-15 05:51:48 +00008#include "llvm/Bytecode/Reader.h"
Chris Lattner92101ac2001-08-23 17:05:04 +00009#include "llvm/Assembly/Writer.h"
Chris Lattnerf8f2afb2001-10-18 21:55:32 +000010#include "llvm/DerivedTypes.h"
Chris Lattnere43db882001-10-27 04:15:57 +000011#include "llvm/Transforms/Linker.h"
Chris Lattner92101ac2001-08-23 17:05:04 +000012#include <algorithm>
Chris Lattner697954c2002-01-20 22:54:45 +000013using std::string;
14using std::cout;
15using std::cin;
Chris Lattner92101ac2001-08-23 17:05:04 +000016
17enum CommandID {
Chris Lattner86660982001-08-27 05:16:50 +000018 Quit, Help, // Basics
19 Print, Info, List, StackTrace, Up, Down, // Inspection
20 Next, Step, Run, Finish, Call, // Control flow changes
21 Break, Watch, // Debugging
Chris Lattner43e3f7c2001-10-27 08:43:52 +000022 Load, Flush,
23 TraceOpt, ProfileOpt // Toggle features
Chris Lattner92101ac2001-08-23 17:05:04 +000024};
25
26// CommandTable - Build a lookup table for the commands available to the user...
27static struct CommandTableElement {
28 const char *Name;
29 enum CommandID CID;
30
31 inline bool operator<(const CommandTableElement &E) const {
32 return string(Name) < string(E.Name);
33 }
34 inline bool operator==(const string &S) const {
35 return string(Name) == S;
36 }
37} CommandTable[] = {
38 { "quit" , Quit }, { "q", Quit }, { "", Quit }, // Empty str = eof
39 { "help" , Help }, { "h", Help },
40
41 { "print" , Print }, { "p", Print },
42 { "list" , List },
Chris Lattner86660982001-08-27 05:16:50 +000043 { "info" , Info },
Chris Lattner92101ac2001-08-23 17:05:04 +000044 { "backtrace", StackTrace }, { "bt", StackTrace }, { "where", StackTrace },
45 { "up" , Up },
46 { "down" , Down },
47
48 { "next" , Next }, { "n", Next },
49 { "step" , Step }, { "s", Step },
50 { "run" , Run },
51 { "finish" , Finish },
52 { "call" , Call },
53
54 { "break" , Break }, { "b", Break },
55 { "watch" , Watch },
56
57 { "load" , Load },
58 { "flush" , Flush },
Chris Lattner43e3f7c2001-10-27 08:43:52 +000059
60 { "trace" , TraceOpt },
61 { "profile" , ProfileOpt },
Chris Lattner92101ac2001-08-23 17:05:04 +000062};
63static CommandTableElement *CommandTableEnd =
64 CommandTable+sizeof(CommandTable)/sizeof(CommandTable[0]);
65
66
67//===----------------------------------------------------------------------===//
68// handleUserInput - Enter the input loop for the interpreter. This function
69// returns when the user quits the interpreter.
70//
71void Interpreter::handleUserInput() {
72 bool UserQuit = false;
73
74 // Sort the table...
Chris Lattner697954c2002-01-20 22:54:45 +000075 std::sort(CommandTable, CommandTableEnd);
Chris Lattner92101ac2001-08-23 17:05:04 +000076
77 // Print the instruction that we are stopped at...
78 printCurrentInstruction();
79
80 do {
81 string Command;
Chris Lattner697954c2002-01-20 22:54:45 +000082 cout << "lli> " << std::flush;
Chris Lattner92101ac2001-08-23 17:05:04 +000083 cin >> Command;
84
85 CommandTableElement *E = find(CommandTable, CommandTableEnd, Command);
86
87 if (E == CommandTableEnd) {
88 cout << "Error: '" << Command << "' not recognized!\n";
89 continue;
90 }
91
92 switch (E->CID) {
93 case Quit: UserQuit = true; break;
Chris Lattner2e42d3a2001-10-15 05:51:48 +000094 case Load:
95 cin >> Command;
96 loadModule(Command);
97 break;
98 case Flush: flushModule(); break;
Chris Lattner92101ac2001-08-23 17:05:04 +000099 case Print:
100 cin >> Command;
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000101 print(Command);
Chris Lattner92101ac2001-08-23 17:05:04 +0000102 break;
Chris Lattner86660982001-08-27 05:16:50 +0000103 case Info:
104 cin >> Command;
105 infoValue(Command);
106 break;
107
Chris Lattner92101ac2001-08-23 17:05:04 +0000108 case List: list(); break;
109 case StackTrace: printStackTrace(); break;
110 case Up:
Chris Lattner461f02f2001-11-07 05:31:27 +0000111 if (CurFrame > 0) { --CurFrame; printStackFrame(); }
Chris Lattner92101ac2001-08-23 17:05:04 +0000112 else cout << "Error: Already at root of stack!\n";
113 break;
114 case Down:
Chris Lattner461f02f2001-11-07 05:31:27 +0000115 if ((unsigned)CurFrame < ECStack.size()-1) {
116 ++CurFrame;
117 printStackFrame();
118 } else
119 cout << "Error: Already at bottom of stack!\n";
Chris Lattner92101ac2001-08-23 17:05:04 +0000120 break;
121 case Next: nextInstruction(); break;
122 case Step: stepInstruction(); break;
123 case Run: run(); break;
124 case Finish: finish(); break;
125 case Call:
126 cin >> Command;
127 callMethod(Command); // Enter the specified method
128 finish(); // Run until it's complete
129 break;
130
Chris Lattner43e3f7c2001-10-27 08:43:52 +0000131 case TraceOpt:
132 Trace = !Trace;
133 cout << "Tracing " << (Trace ? "enabled\n" : "disabled\n");
134 break;
135
136 case ProfileOpt:
137 Profile = !Profile;
138 cout << "Profiling " << (Trace ? "enabled\n" : "disabled\n");
139 break;
140
Chris Lattner92101ac2001-08-23 17:05:04 +0000141 default:
142 cout << "Command '" << Command << "' unimplemented!\n";
143 break;
144 }
145
146 } while (!UserQuit);
147}
148
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000149//===----------------------------------------------------------------------===//
150// loadModule - Load a new module to execute...
151//
152void Interpreter::loadModule(const string &Filename) {
Chris Lattnere43db882001-10-27 04:15:57 +0000153 string ErrorMsg;
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000154 if (CurMod && !flushModule()) return; // Kill current execution
155
Chris Lattnere43db882001-10-27 04:15:57 +0000156 CurMod = ParseBytecodeFile(Filename, &ErrorMsg);
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000157 if (CurMod == 0) {
Chris Lattnere43db882001-10-27 04:15:57 +0000158 cout << "Error parsing '" << Filename << "': No module loaded: "
159 << ErrorMsg << "\n";
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000160 return;
161 }
Chris Lattner5af0c482001-11-07 04:23:00 +0000162 CW.setModule(CurMod); // Update Writer
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000163
Chris Lattner7b83b1d2002-03-11 17:52:43 +0000164#if 0
Chris Lattnera5637fc2001-10-30 16:40:37 +0000165 string RuntimeLib = getCurrentExecutablePath();
166 if (!RuntimeLib.empty()) RuntimeLib += "/";
167 RuntimeLib += "RuntimeLib.bc";
168
Chris Lattnere43db882001-10-27 04:15:57 +0000169 if (Module *SupportLib = ParseBytecodeFile(RuntimeLib, &ErrorMsg)) {
170 if (LinkModules(CurMod, SupportLib, &ErrorMsg))
Chris Lattner697954c2002-01-20 22:54:45 +0000171 std::cerr << "Error Linking runtime library into current module: "
172 << ErrorMsg << "\n";
Chris Lattnere43db882001-10-27 04:15:57 +0000173 } else {
Chris Lattner697954c2002-01-20 22:54:45 +0000174 std::cerr << "Error loading runtime library '"+RuntimeLib+"': "
175 << ErrorMsg << "\n";
Chris Lattnere43db882001-10-27 04:15:57 +0000176 }
Chris Lattner7b83b1d2002-03-11 17:52:43 +0000177#endif
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000178}
179
180
181//===----------------------------------------------------------------------===//
182// flushModule - Return true if the current program has been unloaded.
183//
184bool Interpreter::flushModule() {
185 if (CurMod == 0) {
186 cout << "Error flushing: No module loaded!\n";
187 return false;
188 }
189
190 if (!ECStack.empty()) {
191 // TODO: if use is not sure, return false
192 cout << "Killing current execution!\n";
193 ECStack.clear();
194 CurFrame = -1;
195 }
196
Chris Lattner5af0c482001-11-07 04:23:00 +0000197 CW.setModule(0);
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000198 delete CurMod;
199 CurMod = 0;
200 ExitCode = 0;
201 return true;
202}
Chris Lattner92101ac2001-08-23 17:05:04 +0000203
204//===----------------------------------------------------------------------===//
205// setBreakpoint - Enable a breakpoint at the specified location
206//
207void Interpreter::setBreakpoint(const string &Name) {
208 Value *PickedVal = ChooseOneOption(Name, LookupMatchingNames(Name));
209 // TODO: Set a breakpoint on PickedVal
210}
211
212//===----------------------------------------------------------------------===//
213// callMethod - Enter the specified method...
214//
215bool Interpreter::callMethod(const string &Name) {
Chris Lattner697954c2002-01-20 22:54:45 +0000216 std::vector<Value*> Options = LookupMatchingNames(Name);
Chris Lattner92101ac2001-08-23 17:05:04 +0000217
218 for (unsigned i = 0; i < Options.size(); ++i) { // Remove nonmethod matches...
Chris Lattner1d87bcf2001-10-01 20:11:19 +0000219 if (!isa<Method>(Options[i])) {
Chris Lattner92101ac2001-08-23 17:05:04 +0000220 Options.erase(Options.begin()+i);
221 --i;
222 }
223 }
224
225 Value *PickedMeth = ChooseOneOption(Name, Options);
226 if (PickedMeth == 0)
227 return true;
228
Chris Lattner9636a912001-10-01 16:18:37 +0000229 Method *M = cast<Method>(PickedMeth);
Chris Lattner365a76e2001-09-10 04:49:44 +0000230
Chris Lattner697954c2002-01-20 22:54:45 +0000231 std::vector<GenericValue> Args;
Chris Lattner365a76e2001-09-10 04:49:44 +0000232 // TODO, get args from user...
233
234 callMethod(M, Args); // Start executing it...
Chris Lattner92101ac2001-08-23 17:05:04 +0000235
236 // Reset the current frame location to the top of stack
237 CurFrame = ECStack.size()-1;
238
239 return false;
240}
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000241
Chris Lattner697954c2002-01-20 22:54:45 +0000242static void *CreateArgv(const std::vector<string> &InputArgv) {
Chris Lattner204eec32001-10-27 05:54:31 +0000243 // Pointers are 64 bits...
Chris Lattnerde51dd82001-11-26 19:20:16 +0000244 uint64_t *Result = new PointerTy[InputArgv.size()+1];
Chris Lattner204eec32001-10-27 05:54:31 +0000245
246 for (unsigned i = 0; i < InputArgv.size(); ++i) {
247 unsigned Size = InputArgv[i].size()+1;
248 char *Dest = new char[Size];
249 copy(InputArgv[i].begin(), InputArgv[i].end(), Dest);
250 Dest[Size-1] = 0;
Chris Lattnerde51dd82001-11-26 19:20:16 +0000251 Result[i] = (PointerTy)Dest;
Chris Lattner204eec32001-10-27 05:54:31 +0000252 }
253
254 Result[InputArgv.size()] = 0;
255 return Result;
256}
257
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000258
259// callMainMethod - This is a nasty gross hack that will dissapear when
260// callMethod can parse command line options and stuff for us.
261//
262bool Interpreter::callMainMethod(const string &Name,
Chris Lattner697954c2002-01-20 22:54:45 +0000263 const std::vector<string> &InputArgv) {
264 std::vector<Value*> Options = LookupMatchingNames(Name);
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000265
266 for (unsigned i = 0; i < Options.size(); ++i) { // Remove nonmethod matches...
267 if (!isa<Method>(Options[i])) {
268 Options.erase(Options.begin()+i);
269 --i;
270 }
271 }
272
273 Value *PickedMeth = ChooseOneOption(Name, Options);
274 if (PickedMeth == 0)
275 return true;
276
277 Method *M = cast<Method>(PickedMeth);
278 const MethodType *MT = M->getMethodType();
279
Chris Lattner697954c2002-01-20 22:54:45 +0000280 std::vector<GenericValue> Args;
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000281 switch (MT->getParamTypes().size()) {
282 default:
283 cout << "Unknown number of arguments to synthesize for '" << Name << "'!\n";
284 return true;
285 case 2: {
286 PointerType *SPP = PointerType::get(PointerType::get(Type::SByteTy));
287 if (MT->getParamTypes()[1] != SPP) {
Chris Lattner461f02f2001-11-07 05:31:27 +0000288 CW << "Second argument of '" << Name << "' should have type: '"
289 << SPP << "'!\n";
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000290 return true;
291 }
Chris Lattner204eec32001-10-27 05:54:31 +0000292
Chris Lattnerc2593162001-10-27 08:28:11 +0000293 GenericValue GV; GV.PointerVal = (uint64_t)CreateArgv(InputArgv);
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000294 Args.push_back(GV);
295 }
296 // fallthrough
297 case 1:
298 if (!MT->getParamTypes()[0]->isIntegral()) {
299 cout << "First argument of '" << Name << "' should be integral!\n";
300 return true;
301 } else {
Chris Lattner204eec32001-10-27 05:54:31 +0000302 GenericValue GV; GV.UIntVal = InputArgv.size();
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000303 Args.insert(Args.begin(), GV);
304 }
305 // fallthrough
306 case 0:
307 break;
308 }
309
310 callMethod(M, Args); // Start executing it...
311
312 // Reset the current frame location to the top of stack
313 CurFrame = ECStack.size()-1;
314
315 return false;
316}
Chris Lattner461f02f2001-11-07 05:31:27 +0000317
318
319
320void Interpreter::list() {
321 if (ECStack.empty())
322 cout << "Error: No program executing!\n";
323 else
324 CW << ECStack[CurFrame].CurMethod; // Just print the method out...
325}
326
327void Interpreter::printStackTrace() {
328 if (ECStack.empty()) cout << "No program executing!\n";
329
330 for (unsigned i = 0; i < ECStack.size(); ++i) {
331 printStackFrame((int)i);
332 }
333}