blob: 0ed0f04b15b1d7c0f5db71f2320d30bebb6215e2 [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 Lattner92101ac2001-08-23 17:05:04 +0000118 finish(); // Run until it's complete
119 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);
132}
133
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000134//===----------------------------------------------------------------------===//
Chris Lattner92101ac2001-08-23 17:05:04 +0000135// setBreakpoint - Enable a breakpoint at the specified location
136//
Chris Lattnerda82ed52003-05-08 16:18:31 +0000137void Interpreter::setBreakpoint(const std::string &Name) {
Chris Lattner92101ac2001-08-23 17:05:04 +0000138 Value *PickedVal = ChooseOneOption(Name, LookupMatchingNames(Name));
139 // TODO: Set a breakpoint on PickedVal
140}
141
142//===----------------------------------------------------------------------===//
Chris Lattnerda82ed52003-05-08 16:18:31 +0000143// callFunction - Enter the specified function...
Chris Lattner92101ac2001-08-23 17:05:04 +0000144//
Chris Lattnerda82ed52003-05-08 16:18:31 +0000145bool Interpreter::callFunction(const std::string &Name) {
Chris Lattner697954c2002-01-20 22:54:45 +0000146 std::vector<Value*> Options = LookupMatchingNames(Name);
Chris Lattner92101ac2001-08-23 17:05:04 +0000147
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000148 for (unsigned i = 0; i < Options.size(); ++i) { // Remove non-fn matches...
Chris Lattnerb408b122002-03-29 03:57:15 +0000149 if (!isa<Function>(Options[i])) {
Chris Lattner92101ac2001-08-23 17:05:04 +0000150 Options.erase(Options.begin()+i);
151 --i;
152 }
153 }
154
155 Value *PickedMeth = ChooseOneOption(Name, Options);
156 if (PickedMeth == 0)
157 return true;
158
Chris Lattnerb408b122002-03-29 03:57:15 +0000159 Function *F = cast<Function>(PickedMeth);
Chris Lattner365a76e2001-09-10 04:49:44 +0000160
Chris Lattner697954c2002-01-20 22:54:45 +0000161 std::vector<GenericValue> Args;
Chris Lattner365a76e2001-09-10 04:49:44 +0000162 // TODO, get args from user...
163
Chris Lattnerda82ed52003-05-08 16:18:31 +0000164 callFunction(F, Args); // Start executing it...
Chris Lattner92101ac2001-08-23 17:05:04 +0000165
166 // Reset the current frame location to the top of stack
167 CurFrame = ECStack.size()-1;
168
169 return false;
170}
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000171
Chris Lattnerda82ed52003-05-08 16:18:31 +0000172// callMainFunction - This is a nasty gross hack that will dissapear when
173// callFunction can parse command line options and stuff for us.
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000174//
Chris Lattnerda82ed52003-05-08 16:18:31 +0000175bool Interpreter::callMainFunction(const std::string &Name,
176 const std::vector<std::string> &InputArgv) {
Chris Lattner697954c2002-01-20 22:54:45 +0000177 std::vector<Value*> Options = LookupMatchingNames(Name);
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000178
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000179 for (unsigned i = 0; i < Options.size(); ++i) { // Remove non-fn matches...
Chris Lattnerb408b122002-03-29 03:57:15 +0000180 if (!isa<Function>(Options[i])) {
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000181 Options.erase(Options.begin()+i);
182 --i;
183 }
184 }
185
186 Value *PickedMeth = ChooseOneOption(Name, Options);
187 if (PickedMeth == 0)
188 return true;
189
Chris Lattnerb408b122002-03-29 03:57:15 +0000190 Function *M = cast<Function>(PickedMeth);
191 const FunctionType *MT = M->getFunctionType();
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000192
Chris Lattner697954c2002-01-20 22:54:45 +0000193 std::vector<GenericValue> Args;
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000194 switch (MT->getParamTypes().size()) {
195 default:
Chris Lattnerda82ed52003-05-08 16:18:31 +0000196 std::cout << "Unknown number of arguments to synthesize for '" << Name
197 << "'!\n";
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000198 return true;
199 case 2: {
200 PointerType *SPP = PointerType::get(PointerType::get(Type::SByteTy));
201 if (MT->getParamTypes()[1] != SPP) {
Chris Lattner461f02f2001-11-07 05:31:27 +0000202 CW << "Second argument of '" << Name << "' should have type: '"
203 << SPP << "'!\n";
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000204 return true;
205 }
Chris Lattner204eec32001-10-27 05:54:31 +0000206
Chris Lattnerfe11a972002-12-23 23:59:41 +0000207 Args.push_back(PTOGV(CreateArgv(InputArgv)));
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000208 }
209 // fallthrough
210 case 1:
Chris Lattner0c4e8862002-09-03 01:08:28 +0000211 if (!MT->getParamTypes()[0]->isInteger()) {
Chris Lattnerda82ed52003-05-08 16:18:31 +0000212 std::cout << "First argument of '" << Name << "' should be an integer!\n";
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000213 return true;
214 } else {
Chris Lattner204eec32001-10-27 05:54:31 +0000215 GenericValue GV; GV.UIntVal = InputArgv.size();
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000216 Args.insert(Args.begin(), GV);
217 }
218 // fallthrough
219 case 0:
220 break;
221 }
222
Chris Lattnerda82ed52003-05-08 16:18:31 +0000223 callFunction(M, Args); // Start executing it...
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000224
225 // Reset the current frame location to the top of stack
226 CurFrame = ECStack.size()-1;
227
228 return false;
229}
Chris Lattner461f02f2001-11-07 05:31:27 +0000230
231
232
233void Interpreter::list() {
234 if (ECStack.empty())
Chris Lattnerda82ed52003-05-08 16:18:31 +0000235 std::cout << "Error: No program executing!\n";
Chris Lattner461f02f2001-11-07 05:31:27 +0000236 else
Chris Lattnerda82ed52003-05-08 16:18:31 +0000237 CW << ECStack[CurFrame].CurFunction; // Just print the function out...
Chris Lattner461f02f2001-11-07 05:31:27 +0000238}
239
240void Interpreter::printStackTrace() {
Chris Lattnerda82ed52003-05-08 16:18:31 +0000241 if (ECStack.empty()) std::cout << "No program executing!\n";
Chris Lattner461f02f2001-11-07 05:31:27 +0000242
243 for (unsigned i = 0; i < ECStack.size(); ++i) {
244 printStackFrame((int)i);
245 }
246}