blob: 3f4493d19be8f30d031a79318f821820bc716966 [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>
13
14enum CommandID {
Chris Lattner86660982001-08-27 05:16:50 +000015 Quit, Help, // Basics
16 Print, Info, List, StackTrace, Up, Down, // Inspection
17 Next, Step, Run, Finish, Call, // Control flow changes
18 Break, Watch, // Debugging
Chris Lattnerfe11a972002-12-23 23:59:41 +000019 Flush,
20 TraceOpt, // Toggle features
Chris Lattner92101ac2001-08-23 17:05:04 +000021};
22
23// CommandTable - Build a lookup table for the commands available to the user...
24static struct CommandTableElement {
25 const char *Name;
26 enum CommandID CID;
27
28 inline bool operator<(const CommandTableElement &E) const {
Chris Lattnerda82ed52003-05-08 16:18:31 +000029 return std::string(Name) < std::string(E.Name);
Chris Lattner92101ac2001-08-23 17:05:04 +000030 }
Chris Lattnerda82ed52003-05-08 16:18:31 +000031 inline bool operator==(const std::string &S) const {
32 return std::string(Name) == S;
Chris Lattner92101ac2001-08-23 17:05:04 +000033 }
34} CommandTable[] = {
35 { "quit" , Quit }, { "q", Quit }, { "", Quit }, // Empty str = eof
36 { "help" , Help }, { "h", Help },
37
38 { "print" , Print }, { "p", Print },
39 { "list" , List },
Chris Lattner86660982001-08-27 05:16:50 +000040 { "info" , Info },
Chris Lattner92101ac2001-08-23 17:05:04 +000041 { "backtrace", StackTrace }, { "bt", StackTrace }, { "where", StackTrace },
42 { "up" , Up },
43 { "down" , Down },
44
45 { "next" , Next }, { "n", Next },
46 { "step" , Step }, { "s", Step },
47 { "run" , Run },
48 { "finish" , Finish },
49 { "call" , Call },
50
51 { "break" , Break }, { "b", Break },
52 { "watch" , Watch },
53
Chris Lattner92101ac2001-08-23 17:05:04 +000054 { "flush" , Flush },
Chris Lattner43e3f7c2001-10-27 08:43:52 +000055
56 { "trace" , TraceOpt },
Chris Lattner92101ac2001-08-23 17:05:04 +000057};
58static CommandTableElement *CommandTableEnd =
59 CommandTable+sizeof(CommandTable)/sizeof(CommandTable[0]);
60
61
62//===----------------------------------------------------------------------===//
63// handleUserInput - Enter the input loop for the interpreter. This function
64// returns when the user quits the interpreter.
65//
66void Interpreter::handleUserInput() {
67 bool UserQuit = false;
68
69 // Sort the table...
Chris Lattner697954c2002-01-20 22:54:45 +000070 std::sort(CommandTable, CommandTableEnd);
Chris Lattner92101ac2001-08-23 17:05:04 +000071
72 // Print the instruction that we are stopped at...
73 printCurrentInstruction();
74
75 do {
Chris Lattnerda82ed52003-05-08 16:18:31 +000076 std::string Command;
77 std::cout << "lli> " << std::flush;
78 std::cin >> Command;
Chris Lattner92101ac2001-08-23 17:05:04 +000079
80 CommandTableElement *E = find(CommandTable, CommandTableEnd, Command);
81
82 if (E == CommandTableEnd) {
Chris Lattnerda82ed52003-05-08 16:18:31 +000083 std::cout << "Error: '" << Command << "' not recognized!\n";
Chris Lattner92101ac2001-08-23 17:05:04 +000084 continue;
85 }
86
87 switch (E->CID) {
88 case Quit: UserQuit = true; break;
89 case Print:
Chris Lattnerda82ed52003-05-08 16:18:31 +000090 std::cin >> Command;
Chris Lattner2e42d3a2001-10-15 05:51:48 +000091 print(Command);
Chris Lattner92101ac2001-08-23 17:05:04 +000092 break;
Chris Lattner86660982001-08-27 05:16:50 +000093 case Info:
Chris Lattnerda82ed52003-05-08 16:18:31 +000094 std::cin >> Command;
Chris Lattner86660982001-08-27 05:16:50 +000095 infoValue(Command);
96 break;
97
Chris Lattner92101ac2001-08-23 17:05:04 +000098 case List: list(); break;
99 case StackTrace: printStackTrace(); break;
100 case Up:
Chris Lattner461f02f2001-11-07 05:31:27 +0000101 if (CurFrame > 0) { --CurFrame; printStackFrame(); }
Chris Lattnerda82ed52003-05-08 16:18:31 +0000102 else std::cout << "Error: Already at root of stack!\n";
Chris Lattner92101ac2001-08-23 17:05:04 +0000103 break;
104 case Down:
Chris Lattner461f02f2001-11-07 05:31:27 +0000105 if ((unsigned)CurFrame < ECStack.size()-1) {
106 ++CurFrame;
107 printStackFrame();
108 } else
Chris Lattnerda82ed52003-05-08 16:18:31 +0000109 std::cout << "Error: Already at bottom of stack!\n";
Chris Lattner92101ac2001-08-23 17:05:04 +0000110 break;
111 case Next: nextInstruction(); break;
112 case Step: stepInstruction(); break;
113 case Run: run(); break;
114 case Finish: finish(); break;
115 case Call:
Chris Lattnerda82ed52003-05-08 16:18:31 +0000116 std::cin >> Command;
117 callFunction(Command); // Enter the specified function
Chris Lattner44edb6b2003-05-14 14:21:30 +0000118 finish(); // Run until it's complete
Chris Lattner92101ac2001-08-23 17:05:04 +0000119 break;
120
Chris Lattner43e3f7c2001-10-27 08:43:52 +0000121 case TraceOpt:
122 Trace = !Trace;
Chris Lattnerda82ed52003-05-08 16:18:31 +0000123 std::cout << "Tracing " << (Trace ? "enabled\n" : "disabled\n");
Chris Lattner43e3f7c2001-10-27 08:43:52 +0000124 break;
125
Chris Lattner92101ac2001-08-23 17:05:04 +0000126 default:
Chris Lattnerda82ed52003-05-08 16:18:31 +0000127 std::cout << "Command '" << Command << "' unimplemented!\n";
Chris Lattner92101ac2001-08-23 17:05:04 +0000128 break;
129 }
130
131 } while (!UserQuit);
Chris Lattner44edb6b2003-05-14 14:21:30 +0000132 AtExitHandlers.clear();
Chris Lattner92101ac2001-08-23 17:05:04 +0000133}
134
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000135//===----------------------------------------------------------------------===//
Chris Lattner92101ac2001-08-23 17:05:04 +0000136// setBreakpoint - Enable a breakpoint at the specified location
137//
Chris Lattnerda82ed52003-05-08 16:18:31 +0000138void Interpreter::setBreakpoint(const std::string &Name) {
Chris Lattner92101ac2001-08-23 17:05:04 +0000139 Value *PickedVal = ChooseOneOption(Name, LookupMatchingNames(Name));
140 // TODO: Set a breakpoint on PickedVal
141}
142
143//===----------------------------------------------------------------------===//
Chris Lattnerda82ed52003-05-08 16:18:31 +0000144// callFunction - Enter the specified function...
Chris Lattner92101ac2001-08-23 17:05:04 +0000145//
Chris Lattnerda82ed52003-05-08 16:18:31 +0000146bool Interpreter::callFunction(const std::string &Name) {
Chris Lattner697954c2002-01-20 22:54:45 +0000147 std::vector<Value*> Options = LookupMatchingNames(Name);
Chris Lattner92101ac2001-08-23 17:05:04 +0000148
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000149 for (unsigned i = 0; i < Options.size(); ++i) { // Remove non-fn matches...
Chris Lattnerb408b122002-03-29 03:57:15 +0000150 if (!isa<Function>(Options[i])) {
Chris Lattner92101ac2001-08-23 17:05:04 +0000151 Options.erase(Options.begin()+i);
152 --i;
153 }
154 }
155
156 Value *PickedMeth = ChooseOneOption(Name, Options);
157 if (PickedMeth == 0)
158 return true;
159
Chris Lattnerb408b122002-03-29 03:57:15 +0000160 Function *F = cast<Function>(PickedMeth);
Chris Lattner365a76e2001-09-10 04:49:44 +0000161
Chris Lattner697954c2002-01-20 22:54:45 +0000162 std::vector<GenericValue> Args;
Chris Lattner365a76e2001-09-10 04:49:44 +0000163 // TODO, get args from user...
164
Chris Lattnerda82ed52003-05-08 16:18:31 +0000165 callFunction(F, Args); // Start executing it...
Chris Lattner92101ac2001-08-23 17:05:04 +0000166
167 // Reset the current frame location to the top of stack
168 CurFrame = ECStack.size()-1;
169
170 return false;
171}
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000172
Chris Lattnerda82ed52003-05-08 16:18:31 +0000173// callMainFunction - This is a nasty gross hack that will dissapear when
174// callFunction can parse command line options and stuff for us.
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000175//
Chris Lattnerda82ed52003-05-08 16:18:31 +0000176bool Interpreter::callMainFunction(const std::string &Name,
177 const std::vector<std::string> &InputArgv) {
Chris Lattner697954c2002-01-20 22:54:45 +0000178 std::vector<Value*> Options = LookupMatchingNames(Name);
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000179
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000180 for (unsigned i = 0; i < Options.size(); ++i) { // Remove non-fn matches...
Chris Lattnerb408b122002-03-29 03:57:15 +0000181 if (!isa<Function>(Options[i])) {
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000182 Options.erase(Options.begin()+i);
183 --i;
184 }
185 }
186
187 Value *PickedMeth = ChooseOneOption(Name, Options);
188 if (PickedMeth == 0)
189 return true;
190
Chris Lattnerb408b122002-03-29 03:57:15 +0000191 Function *M = cast<Function>(PickedMeth);
192 const FunctionType *MT = M->getFunctionType();
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000193
Chris Lattner697954c2002-01-20 22:54:45 +0000194 std::vector<GenericValue> Args;
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000195 switch (MT->getParamTypes().size()) {
196 default:
Chris Lattnerda82ed52003-05-08 16:18:31 +0000197 std::cout << "Unknown number of arguments to synthesize for '" << Name
198 << "'!\n";
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000199 return true;
200 case 2: {
201 PointerType *SPP = PointerType::get(PointerType::get(Type::SByteTy));
202 if (MT->getParamTypes()[1] != SPP) {
Chris Lattner461f02f2001-11-07 05:31:27 +0000203 CW << "Second argument of '" << Name << "' should have type: '"
204 << SPP << "'!\n";
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000205 return true;
206 }
Chris Lattner204eec32001-10-27 05:54:31 +0000207
Chris Lattnerfe11a972002-12-23 23:59:41 +0000208 Args.push_back(PTOGV(CreateArgv(InputArgv)));
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000209 }
210 // fallthrough
211 case 1:
Chris Lattner0c4e8862002-09-03 01:08:28 +0000212 if (!MT->getParamTypes()[0]->isInteger()) {
Chris Lattnerda82ed52003-05-08 16:18:31 +0000213 std::cout << "First argument of '" << Name << "' should be an integer!\n";
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000214 return true;
215 } else {
Chris Lattner204eec32001-10-27 05:54:31 +0000216 GenericValue GV; GV.UIntVal = InputArgv.size();
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000217 Args.insert(Args.begin(), GV);
218 }
219 // fallthrough
220 case 0:
221 break;
222 }
223
Chris Lattnerda82ed52003-05-08 16:18:31 +0000224 callFunction(M, Args); // Start executing it...
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000225
226 // Reset the current frame location to the top of stack
227 CurFrame = ECStack.size()-1;
228
229 return false;
230}
Chris Lattner461f02f2001-11-07 05:31:27 +0000231
232
233
234void Interpreter::list() {
235 if (ECStack.empty())
Chris Lattnerda82ed52003-05-08 16:18:31 +0000236 std::cout << "Error: No program executing!\n";
Chris Lattner461f02f2001-11-07 05:31:27 +0000237 else
Chris Lattnerda82ed52003-05-08 16:18:31 +0000238 CW << ECStack[CurFrame].CurFunction; // Just print the function out...
Chris Lattner461f02f2001-11-07 05:31:27 +0000239}
240
241void Interpreter::printStackTrace() {
Chris Lattnerda82ed52003-05-08 16:18:31 +0000242 if (ECStack.empty()) std::cout << "No program executing!\n";
Chris Lattner461f02f2001-11-07 05:31:27 +0000243
244 for (unsigned i = 0; i < ECStack.size(); ++i) {
245 printStackFrame((int)i);
246 }
247}