blob: 018e6f7c0f40d69b8a44612274a0b7195293186e [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 Lattnerf8f2afb2001-10-18 21:55:32 +00009#include "llvm/DerivedTypes.h"
Chris Lattnere43db882001-10-27 04:15:57 +000010#include "llvm/Transforms/Linker.h"
Chris Lattner92101ac2001-08-23 17:05:04 +000011#include <algorithm>
Chris Lattner697954c2002-01-20 22:54:45 +000012using std::string;
13using std::cout;
14using std::cin;
Chris Lattner92101ac2001-08-23 17:05:04 +000015
16enum CommandID {
Chris Lattner86660982001-08-27 05:16:50 +000017 Quit, Help, // Basics
18 Print, Info, List, StackTrace, Up, Down, // Inspection
19 Next, Step, Run, Finish, Call, // Control flow changes
20 Break, Watch, // Debugging
Chris Lattner43e3f7c2001-10-27 08:43:52 +000021 Load, Flush,
22 TraceOpt, ProfileOpt // Toggle features
Chris Lattner92101ac2001-08-23 17:05:04 +000023};
24
25// CommandTable - Build a lookup table for the commands available to the user...
26static struct CommandTableElement {
27 const char *Name;
28 enum CommandID CID;
29
30 inline bool operator<(const CommandTableElement &E) const {
31 return string(Name) < string(E.Name);
32 }
33 inline bool operator==(const string &S) const {
34 return string(Name) == S;
35 }
36} CommandTable[] = {
37 { "quit" , Quit }, { "q", Quit }, { "", Quit }, // Empty str = eof
38 { "help" , Help }, { "h", Help },
39
40 { "print" , Print }, { "p", Print },
41 { "list" , List },
Chris Lattner86660982001-08-27 05:16:50 +000042 { "info" , Info },
Chris Lattner92101ac2001-08-23 17:05:04 +000043 { "backtrace", StackTrace }, { "bt", StackTrace }, { "where", StackTrace },
44 { "up" , Up },
45 { "down" , Down },
46
47 { "next" , Next }, { "n", Next },
48 { "step" , Step }, { "s", Step },
49 { "run" , Run },
50 { "finish" , Finish },
51 { "call" , Call },
52
53 { "break" , Break }, { "b", Break },
54 { "watch" , Watch },
55
56 { "load" , Load },
57 { "flush" , Flush },
Chris Lattner43e3f7c2001-10-27 08:43:52 +000058
59 { "trace" , TraceOpt },
60 { "profile" , ProfileOpt },
Chris Lattner92101ac2001-08-23 17:05:04 +000061};
62static CommandTableElement *CommandTableEnd =
63 CommandTable+sizeof(CommandTable)/sizeof(CommandTable[0]);
64
65
66//===----------------------------------------------------------------------===//
67// handleUserInput - Enter the input loop for the interpreter. This function
68// returns when the user quits the interpreter.
69//
70void Interpreter::handleUserInput() {
71 bool UserQuit = false;
72
73 // Sort the table...
Chris Lattner697954c2002-01-20 22:54:45 +000074 std::sort(CommandTable, CommandTableEnd);
Chris Lattner92101ac2001-08-23 17:05:04 +000075
76 // Print the instruction that we are stopped at...
77 printCurrentInstruction();
78
79 do {
80 string Command;
Chris Lattner697954c2002-01-20 22:54:45 +000081 cout << "lli> " << std::flush;
Chris Lattner92101ac2001-08-23 17:05:04 +000082 cin >> Command;
83
84 CommandTableElement *E = find(CommandTable, CommandTableEnd, Command);
85
86 if (E == CommandTableEnd) {
87 cout << "Error: '" << Command << "' not recognized!\n";
88 continue;
89 }
90
91 switch (E->CID) {
92 case Quit: UserQuit = true; break;
Chris Lattner2e42d3a2001-10-15 05:51:48 +000093 case Load:
94 cin >> Command;
95 loadModule(Command);
96 break;
97 case Flush: flushModule(); break;
Chris Lattner92101ac2001-08-23 17:05:04 +000098 case Print:
99 cin >> Command;
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000100 print(Command);
Chris Lattner92101ac2001-08-23 17:05:04 +0000101 break;
Chris Lattner86660982001-08-27 05:16:50 +0000102 case Info:
103 cin >> Command;
104 infoValue(Command);
105 break;
106
Chris Lattner92101ac2001-08-23 17:05:04 +0000107 case List: list(); break;
108 case StackTrace: printStackTrace(); break;
109 case Up:
Chris Lattner461f02f2001-11-07 05:31:27 +0000110 if (CurFrame > 0) { --CurFrame; printStackFrame(); }
Chris Lattner92101ac2001-08-23 17:05:04 +0000111 else cout << "Error: Already at root of stack!\n";
112 break;
113 case Down:
Chris Lattner461f02f2001-11-07 05:31:27 +0000114 if ((unsigned)CurFrame < ECStack.size()-1) {
115 ++CurFrame;
116 printStackFrame();
117 } else
118 cout << "Error: Already at bottom of stack!\n";
Chris Lattner92101ac2001-08-23 17:05:04 +0000119 break;
120 case Next: nextInstruction(); break;
121 case Step: stepInstruction(); break;
122 case Run: run(); break;
123 case Finish: finish(); break;
124 case Call:
125 cin >> Command;
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000126 callMethod(Command); // Enter the specified function
Chris Lattner92101ac2001-08-23 17:05:04 +0000127 finish(); // Run until it's complete
128 break;
129
Chris Lattner43e3f7c2001-10-27 08:43:52 +0000130 case TraceOpt:
131 Trace = !Trace;
132 cout << "Tracing " << (Trace ? "enabled\n" : "disabled\n");
133 break;
134
135 case ProfileOpt:
136 Profile = !Profile;
137 cout << "Profiling " << (Trace ? "enabled\n" : "disabled\n");
138 break;
139
Chris Lattner92101ac2001-08-23 17:05:04 +0000140 default:
141 cout << "Command '" << Command << "' unimplemented!\n";
142 break;
143 }
144
145 } while (!UserQuit);
146}
147
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000148//===----------------------------------------------------------------------===//
149// loadModule - Load a new module to execute...
150//
151void Interpreter::loadModule(const string &Filename) {
Chris Lattnere43db882001-10-27 04:15:57 +0000152 string ErrorMsg;
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000153 if (CurMod && !flushModule()) return; // Kill current execution
154
Chris Lattnere43db882001-10-27 04:15:57 +0000155 CurMod = ParseBytecodeFile(Filename, &ErrorMsg);
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000156 if (CurMod == 0) {
Chris Lattnere43db882001-10-27 04:15:57 +0000157 cout << "Error parsing '" << Filename << "': No module loaded: "
158 << ErrorMsg << "\n";
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000159 return;
160 }
Chris Lattner5af0c482001-11-07 04:23:00 +0000161 CW.setModule(CurMod); // Update Writer
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000162
Chris Lattner7b83b1d2002-03-11 17:52:43 +0000163#if 0
Chris Lattnera5637fc2001-10-30 16:40:37 +0000164 string RuntimeLib = getCurrentExecutablePath();
165 if (!RuntimeLib.empty()) RuntimeLib += "/";
166 RuntimeLib += "RuntimeLib.bc";
167
Chris Lattnere43db882001-10-27 04:15:57 +0000168 if (Module *SupportLib = ParseBytecodeFile(RuntimeLib, &ErrorMsg)) {
169 if (LinkModules(CurMod, SupportLib, &ErrorMsg))
Chris Lattner697954c2002-01-20 22:54:45 +0000170 std::cerr << "Error Linking runtime library into current module: "
171 << ErrorMsg << "\n";
Chris Lattnere43db882001-10-27 04:15:57 +0000172 } else {
Chris Lattner697954c2002-01-20 22:54:45 +0000173 std::cerr << "Error loading runtime library '"+RuntimeLib+"': "
174 << ErrorMsg << "\n";
Chris Lattnere43db882001-10-27 04:15:57 +0000175 }
Chris Lattner7b83b1d2002-03-11 17:52:43 +0000176#endif
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000177}
178
179
180//===----------------------------------------------------------------------===//
181// flushModule - Return true if the current program has been unloaded.
182//
183bool Interpreter::flushModule() {
184 if (CurMod == 0) {
185 cout << "Error flushing: No module loaded!\n";
186 return false;
187 }
188
189 if (!ECStack.empty()) {
190 // TODO: if use is not sure, return false
191 cout << "Killing current execution!\n";
192 ECStack.clear();
193 CurFrame = -1;
194 }
195
Chris Lattner5af0c482001-11-07 04:23:00 +0000196 CW.setModule(0);
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000197 delete CurMod;
198 CurMod = 0;
199 ExitCode = 0;
200 return true;
201}
Chris Lattner92101ac2001-08-23 17:05:04 +0000202
203//===----------------------------------------------------------------------===//
204// setBreakpoint - Enable a breakpoint at the specified location
205//
206void Interpreter::setBreakpoint(const string &Name) {
207 Value *PickedVal = ChooseOneOption(Name, LookupMatchingNames(Name));
208 // TODO: Set a breakpoint on PickedVal
209}
210
211//===----------------------------------------------------------------------===//
212// callMethod - Enter the specified method...
213//
214bool Interpreter::callMethod(const string &Name) {
Chris Lattner697954c2002-01-20 22:54:45 +0000215 std::vector<Value*> Options = LookupMatchingNames(Name);
Chris Lattner92101ac2001-08-23 17:05:04 +0000216
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000217 for (unsigned i = 0; i < Options.size(); ++i) { // Remove non-fn matches...
Chris Lattnerb408b122002-03-29 03:57:15 +0000218 if (!isa<Function>(Options[i])) {
Chris Lattner92101ac2001-08-23 17:05:04 +0000219 Options.erase(Options.begin()+i);
220 --i;
221 }
222 }
223
224 Value *PickedMeth = ChooseOneOption(Name, Options);
225 if (PickedMeth == 0)
226 return true;
227
Chris Lattnerb408b122002-03-29 03:57:15 +0000228 Function *F = cast<Function>(PickedMeth);
Chris Lattner365a76e2001-09-10 04:49:44 +0000229
Chris Lattner697954c2002-01-20 22:54:45 +0000230 std::vector<GenericValue> Args;
Chris Lattner365a76e2001-09-10 04:49:44 +0000231 // TODO, get args from user...
232
Chris Lattnerb408b122002-03-29 03:57:15 +0000233 callMethod(F, Args); // Start executing it...
Chris Lattner92101ac2001-08-23 17:05:04 +0000234
235 // Reset the current frame location to the top of stack
236 CurFrame = ECStack.size()-1;
237
238 return false;
239}
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000240
Chris Lattner697954c2002-01-20 22:54:45 +0000241static void *CreateArgv(const std::vector<string> &InputArgv) {
Chris Lattner204eec32001-10-27 05:54:31 +0000242 // Pointers are 64 bits...
Chris Lattnerde51dd82001-11-26 19:20:16 +0000243 uint64_t *Result = new PointerTy[InputArgv.size()+1];
Chris Lattner204eec32001-10-27 05:54:31 +0000244
245 for (unsigned i = 0; i < InputArgv.size(); ++i) {
246 unsigned Size = InputArgv[i].size()+1;
247 char *Dest = new char[Size];
248 copy(InputArgv[i].begin(), InputArgv[i].end(), Dest);
249 Dest[Size-1] = 0;
Chris Lattnerde51dd82001-11-26 19:20:16 +0000250 Result[i] = (PointerTy)Dest;
Chris Lattner204eec32001-10-27 05:54:31 +0000251 }
252
253 Result[InputArgv.size()] = 0;
254 return Result;
255}
256
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000257
258// callMainMethod - This is a nasty gross hack that will dissapear when
259// callMethod can parse command line options and stuff for us.
260//
261bool Interpreter::callMainMethod(const string &Name,
Chris Lattner697954c2002-01-20 22:54:45 +0000262 const std::vector<string> &InputArgv) {
263 std::vector<Value*> Options = LookupMatchingNames(Name);
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000264
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000265 for (unsigned i = 0; i < Options.size(); ++i) { // Remove non-fn matches...
Chris Lattnerb408b122002-03-29 03:57:15 +0000266 if (!isa<Function>(Options[i])) {
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000267 Options.erase(Options.begin()+i);
268 --i;
269 }
270 }
271
272 Value *PickedMeth = ChooseOneOption(Name, Options);
273 if (PickedMeth == 0)
274 return true;
275
Chris Lattnerb408b122002-03-29 03:57:15 +0000276 Function *M = cast<Function>(PickedMeth);
277 const FunctionType *MT = M->getFunctionType();
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000278
Chris Lattner697954c2002-01-20 22:54:45 +0000279 std::vector<GenericValue> Args;
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000280 switch (MT->getParamTypes().size()) {
281 default:
282 cout << "Unknown number of arguments to synthesize for '" << Name << "'!\n";
283 return true;
284 case 2: {
285 PointerType *SPP = PointerType::get(PointerType::get(Type::SByteTy));
286 if (MT->getParamTypes()[1] != SPP) {
Chris Lattner461f02f2001-11-07 05:31:27 +0000287 CW << "Second argument of '" << Name << "' should have type: '"
288 << SPP << "'!\n";
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000289 return true;
290 }
Chris Lattner204eec32001-10-27 05:54:31 +0000291
Chris Lattnerc2593162001-10-27 08:28:11 +0000292 GenericValue GV; GV.PointerVal = (uint64_t)CreateArgv(InputArgv);
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000293 Args.push_back(GV);
294 }
295 // fallthrough
296 case 1:
297 if (!MT->getParamTypes()[0]->isIntegral()) {
298 cout << "First argument of '" << Name << "' should be integral!\n";
299 return true;
300 } else {
Chris Lattner204eec32001-10-27 05:54:31 +0000301 GenericValue GV; GV.UIntVal = InputArgv.size();
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000302 Args.insert(Args.begin(), GV);
303 }
304 // fallthrough
305 case 0:
306 break;
307 }
308
309 callMethod(M, Args); // Start executing it...
310
311 // Reset the current frame location to the top of stack
312 CurFrame = ECStack.size()-1;
313
314 return false;
315}
Chris Lattner461f02f2001-11-07 05:31:27 +0000316
317
318
319void Interpreter::list() {
320 if (ECStack.empty())
321 cout << "Error: No program executing!\n";
322 else
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000323 CW << ECStack[CurFrame].CurMethod; // Just print the function out...
Chris Lattner461f02f2001-11-07 05:31:27 +0000324}
325
326void Interpreter::printStackTrace() {
327 if (ECStack.empty()) cout << "No program executing!\n";
328
329 for (unsigned i = 0; i < ECStack.size(); ++i) {
330 printStackFrame((int)i);
331 }
332}