blob: 3d2b1de60a45464f9c1b05a5148d2a232b3891d3 [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 Lattnerfe11a972002-12-23 23:59:41 +000010#include "llvm/Function.h"
Chris Lattnerc8cc4cb2002-05-07 18:36:35 +000011#include "llvm/Transforms/Utils/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 Lattnerfe11a972002-12-23 23:59:41 +000022 Flush,
23 TraceOpt, // 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
Chris Lattner92101ac2001-08-23 17:05:04 +000057 { "flush" , Flush },
Chris Lattner43e3f7c2001-10-27 08:43:52 +000058
59 { "trace" , TraceOpt },
Chris Lattner92101ac2001-08-23 17:05:04 +000060};
61static CommandTableElement *CommandTableEnd =
62 CommandTable+sizeof(CommandTable)/sizeof(CommandTable[0]);
63
64
65//===----------------------------------------------------------------------===//
66// handleUserInput - Enter the input loop for the interpreter. This function
67// returns when the user quits the interpreter.
68//
69void Interpreter::handleUserInput() {
70 bool UserQuit = false;
71
72 // Sort the table...
Chris Lattner697954c2002-01-20 22:54:45 +000073 std::sort(CommandTable, CommandTableEnd);
Chris Lattner92101ac2001-08-23 17:05:04 +000074
75 // Print the instruction that we are stopped at...
76 printCurrentInstruction();
77
78 do {
79 string Command;
Chris Lattner697954c2002-01-20 22:54:45 +000080 cout << "lli> " << std::flush;
Chris Lattner92101ac2001-08-23 17:05:04 +000081 cin >> Command;
82
83 CommandTableElement *E = find(CommandTable, CommandTableEnd, Command);
84
85 if (E == CommandTableEnd) {
86 cout << "Error: '" << Command << "' not recognized!\n";
87 continue;
88 }
89
90 switch (E->CID) {
91 case Quit: UserQuit = true; break;
92 case Print:
93 cin >> Command;
Chris Lattner2e42d3a2001-10-15 05:51:48 +000094 print(Command);
Chris Lattner92101ac2001-08-23 17:05:04 +000095 break;
Chris Lattner86660982001-08-27 05:16:50 +000096 case Info:
97 cin >> Command;
98 infoValue(Command);
99 break;
100
Chris Lattner92101ac2001-08-23 17:05:04 +0000101 case List: list(); break;
102 case StackTrace: printStackTrace(); break;
103 case Up:
Chris Lattner461f02f2001-11-07 05:31:27 +0000104 if (CurFrame > 0) { --CurFrame; printStackFrame(); }
Chris Lattner92101ac2001-08-23 17:05:04 +0000105 else cout << "Error: Already at root of stack!\n";
106 break;
107 case Down:
Chris Lattner461f02f2001-11-07 05:31:27 +0000108 if ((unsigned)CurFrame < ECStack.size()-1) {
109 ++CurFrame;
110 printStackFrame();
111 } else
112 cout << "Error: Already at bottom of stack!\n";
Chris Lattner92101ac2001-08-23 17:05:04 +0000113 break;
114 case Next: nextInstruction(); break;
115 case Step: stepInstruction(); break;
116 case Run: run(); break;
117 case Finish: finish(); break;
118 case Call:
119 cin >> Command;
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000120 callMethod(Command); // Enter the specified function
Chris Lattner92101ac2001-08-23 17:05:04 +0000121 finish(); // Run until it's complete
122 break;
123
Chris Lattner43e3f7c2001-10-27 08:43:52 +0000124 case TraceOpt:
125 Trace = !Trace;
126 cout << "Tracing " << (Trace ? "enabled\n" : "disabled\n");
127 break;
128
Chris Lattner92101ac2001-08-23 17:05:04 +0000129 default:
130 cout << "Command '" << Command << "' unimplemented!\n";
131 break;
132 }
133
134 } while (!UserQuit);
135}
136
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000137//===----------------------------------------------------------------------===//
Chris Lattner92101ac2001-08-23 17:05:04 +0000138// setBreakpoint - Enable a breakpoint at the specified location
139//
140void Interpreter::setBreakpoint(const string &Name) {
141 Value *PickedVal = ChooseOneOption(Name, LookupMatchingNames(Name));
142 // TODO: Set a breakpoint on PickedVal
143}
144
145//===----------------------------------------------------------------------===//
146// callMethod - Enter the specified method...
147//
148bool Interpreter::callMethod(const string &Name) {
Chris Lattner697954c2002-01-20 22:54:45 +0000149 std::vector<Value*> Options = LookupMatchingNames(Name);
Chris Lattner92101ac2001-08-23 17:05:04 +0000150
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000151 for (unsigned i = 0; i < Options.size(); ++i) { // Remove non-fn matches...
Chris Lattnerb408b122002-03-29 03:57:15 +0000152 if (!isa<Function>(Options[i])) {
Chris Lattner92101ac2001-08-23 17:05:04 +0000153 Options.erase(Options.begin()+i);
154 --i;
155 }
156 }
157
158 Value *PickedMeth = ChooseOneOption(Name, Options);
159 if (PickedMeth == 0)
160 return true;
161
Chris Lattnerb408b122002-03-29 03:57:15 +0000162 Function *F = cast<Function>(PickedMeth);
Chris Lattner365a76e2001-09-10 04:49:44 +0000163
Chris Lattner697954c2002-01-20 22:54:45 +0000164 std::vector<GenericValue> Args;
Chris Lattner365a76e2001-09-10 04:49:44 +0000165 // TODO, get args from user...
166
Chris Lattnerb408b122002-03-29 03:57:15 +0000167 callMethod(F, Args); // Start executing it...
Chris Lattner92101ac2001-08-23 17:05:04 +0000168
169 // Reset the current frame location to the top of stack
170 CurFrame = ECStack.size()-1;
171
172 return false;
173}
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000174
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000175// callMainMethod - This is a nasty gross hack that will dissapear when
176// callMethod can parse command line options and stuff for us.
177//
178bool Interpreter::callMainMethod(const string &Name,
Chris Lattner697954c2002-01-20 22:54:45 +0000179 const std::vector<string> &InputArgv) {
180 std::vector<Value*> Options = LookupMatchingNames(Name);
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000181
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000182 for (unsigned i = 0; i < Options.size(); ++i) { // Remove non-fn matches...
Chris Lattnerb408b122002-03-29 03:57:15 +0000183 if (!isa<Function>(Options[i])) {
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000184 Options.erase(Options.begin()+i);
185 --i;
186 }
187 }
188
189 Value *PickedMeth = ChooseOneOption(Name, Options);
190 if (PickedMeth == 0)
191 return true;
192
Chris Lattnerb408b122002-03-29 03:57:15 +0000193 Function *M = cast<Function>(PickedMeth);
194 const FunctionType *MT = M->getFunctionType();
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000195
Chris Lattner697954c2002-01-20 22:54:45 +0000196 std::vector<GenericValue> Args;
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000197 switch (MT->getParamTypes().size()) {
198 default:
199 cout << "Unknown number of arguments to synthesize for '" << Name << "'!\n";
200 return true;
201 case 2: {
202 PointerType *SPP = PointerType::get(PointerType::get(Type::SByteTy));
203 if (MT->getParamTypes()[1] != SPP) {
Chris Lattner461f02f2001-11-07 05:31:27 +0000204 CW << "Second argument of '" << Name << "' should have type: '"
205 << SPP << "'!\n";
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000206 return true;
207 }
Chris Lattner204eec32001-10-27 05:54:31 +0000208
Chris Lattnerfe11a972002-12-23 23:59:41 +0000209 Args.push_back(PTOGV(CreateArgv(InputArgv)));
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000210 }
211 // fallthrough
212 case 1:
Chris Lattner0c4e8862002-09-03 01:08:28 +0000213 if (!MT->getParamTypes()[0]->isInteger()) {
214 cout << "First argument of '" << Name << "' should be an integer!\n";
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000215 return true;
216 } else {
Chris Lattner204eec32001-10-27 05:54:31 +0000217 GenericValue GV; GV.UIntVal = InputArgv.size();
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000218 Args.insert(Args.begin(), GV);
219 }
220 // fallthrough
221 case 0:
222 break;
223 }
224
225 callMethod(M, Args); // Start executing it...
226
227 // Reset the current frame location to the top of stack
228 CurFrame = ECStack.size()-1;
229
230 return false;
231}
Chris Lattner461f02f2001-11-07 05:31:27 +0000232
233
234
235void Interpreter::list() {
236 if (ECStack.empty())
237 cout << "Error: No program executing!\n";
238 else
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000239 CW << ECStack[CurFrame].CurMethod; // Just print the function out...
Chris Lattner461f02f2001-11-07 05:31:27 +0000240}
241
242void Interpreter::printStackTrace() {
243 if (ECStack.empty()) cout << "No program executing!\n";
244
245 for (unsigned i = 0; i < ECStack.size(); ++i) {
246 printStackFrame((int)i);
247 }
248}