Change references to the Method class to be references to the Function
[oota-llvm.git] / lib / ExecutionEngine / Interpreter / UserInput.cpp
1 //===-- UserInput.cpp - Interpreter Input Loop support --------------------===//
2 // 
3 //  This file implements the interpreter Input I/O loop.
4 //
5 //===----------------------------------------------------------------------===//
6
7 #include "Interpreter.h"
8 #include "llvm/Bytecode/Reader.h"
9 #include "llvm/Assembly/Writer.h"
10 #include "llvm/DerivedTypes.h"
11 #include "llvm/Transforms/Linker.h"
12 #include <algorithm>
13 using std::string;
14 using std::cout;
15 using std::cin;
16
17 enum CommandID {
18   Quit, Help,                                 // Basics
19   Print, Info, List, StackTrace, Up, Down,    // Inspection
20   Next, Step, Run, Finish, Call,              // Control flow changes
21   Break, Watch,                               // Debugging
22   Load, Flush,
23   TraceOpt, ProfileOpt                              // Toggle features
24 };
25
26 // CommandTable - Build a lookup table for the commands available to the user...
27 static 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       },
43   { "info"     , Info       },
44   { "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      },
59
60   { "trace"    , TraceOpt   },
61   { "profile"  , ProfileOpt },
62 };
63 static 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 //
71 void Interpreter::handleUserInput() {
72   bool UserQuit = false;
73
74   // Sort the table...
75   std::sort(CommandTable, CommandTableEnd);
76
77   // Print the instruction that we are stopped at...
78   printCurrentInstruction();
79
80   do {
81     string Command;
82     cout << "lli> " << std::flush;
83     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;
94     case Load:
95       cin >> Command;
96       loadModule(Command);
97       break;
98     case Flush: flushModule(); break;
99     case Print:
100       cin >> Command;
101       print(Command);
102       break;
103     case Info:
104       cin >> Command;
105       infoValue(Command);
106       break;
107      
108     case List:       list();            break;
109     case StackTrace: printStackTrace(); break;
110     case Up: 
111       if (CurFrame > 0) { --CurFrame; printStackFrame(); }
112       else cout << "Error: Already at root of stack!\n";
113       break;
114     case Down:
115       if ((unsigned)CurFrame < ECStack.size()-1) {
116         ++CurFrame;
117         printStackFrame();
118       } else
119         cout << "Error: Already at bottom of stack!\n";
120       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 function
128       finish();               // Run until it's complete
129       break;
130
131     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
141     default:
142       cout << "Command '" << Command << "' unimplemented!\n";
143       break;
144     }
145
146   } while (!UserQuit);
147 }
148
149 //===----------------------------------------------------------------------===//
150 // loadModule - Load a new module to execute...
151 //
152 void Interpreter::loadModule(const string &Filename) {
153   string ErrorMsg;
154   if (CurMod && !flushModule()) return;  // Kill current execution
155
156   CurMod = ParseBytecodeFile(Filename, &ErrorMsg);
157   if (CurMod == 0) {
158     cout << "Error parsing '" << Filename << "': No module loaded: "
159          << ErrorMsg << "\n";
160     return;
161   }
162   CW.setModule(CurMod);  // Update Writer
163
164 #if 0
165   string RuntimeLib = getCurrentExecutablePath();
166   if (!RuntimeLib.empty()) RuntimeLib += "/";
167   RuntimeLib += "RuntimeLib.bc";
168
169   if (Module *SupportLib = ParseBytecodeFile(RuntimeLib, &ErrorMsg)) {
170     if (LinkModules(CurMod, SupportLib, &ErrorMsg))
171       std::cerr << "Error Linking runtime library into current module: "
172                 << ErrorMsg << "\n";
173   } else {
174     std::cerr << "Error loading runtime library '"+RuntimeLib+"': "
175               << ErrorMsg << "\n";
176   }
177 #endif
178 }
179
180
181 //===----------------------------------------------------------------------===//
182 // flushModule - Return true if the current program has been unloaded.
183 //
184 bool 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
197   CW.setModule(0);
198   delete CurMod;
199   CurMod = 0;
200   ExitCode = 0;
201   return true;
202 }
203
204 //===----------------------------------------------------------------------===//
205 // setBreakpoint - Enable a breakpoint at the specified location
206 //
207 void 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 //
215 bool Interpreter::callMethod(const string &Name) {
216   std::vector<Value*> Options = LookupMatchingNames(Name);
217
218   for (unsigned i = 0; i < Options.size(); ++i) { // Remove non-fn matches...
219     if (!isa<Function>(Options[i])) {
220       Options.erase(Options.begin()+i);
221       --i;
222     }
223   }
224
225   Value *PickedMeth = ChooseOneOption(Name, Options);
226   if (PickedMeth == 0)
227     return true;
228
229   Function *F = cast<Function>(PickedMeth);
230
231   std::vector<GenericValue> Args;
232   // TODO, get args from user...
233
234   callMethod(F, Args);  // Start executing it...
235
236   // Reset the current frame location to the top of stack
237   CurFrame = ECStack.size()-1;
238
239   return false;
240 }
241
242 static void *CreateArgv(const std::vector<string> &InputArgv) {
243   // Pointers are 64 bits...
244   uint64_t *Result = new PointerTy[InputArgv.size()+1];
245
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;
251     Result[i] = (PointerTy)Dest;
252   }
253
254   Result[InputArgv.size()] = 0;
255   return Result;
256 }
257
258
259 // callMainMethod - This is a nasty gross hack that will dissapear when
260 // callMethod can parse command line options and stuff for us.
261 //
262 bool Interpreter::callMainMethod(const string &Name,
263                                  const std::vector<string> &InputArgv) {
264   std::vector<Value*> Options = LookupMatchingNames(Name);
265
266   for (unsigned i = 0; i < Options.size(); ++i) { // Remove non-fn matches...
267     if (!isa<Function>(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   Function *M = cast<Function>(PickedMeth);
278   const FunctionType *MT = M->getFunctionType();
279
280   std::vector<GenericValue> Args;
281   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) {
288       CW << "Second argument of '" << Name << "' should have type: '"
289          << SPP << "'!\n";
290       return true;
291     }
292
293     GenericValue GV; GV.PointerVal = (uint64_t)CreateArgv(InputArgv);
294     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 {
302       GenericValue GV; GV.UIntVal = InputArgv.size();
303       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 }
317
318
319
320 void Interpreter::list() {
321   if (ECStack.empty())
322     cout << "Error: No program executing!\n";
323   else
324     CW << ECStack[CurFrame].CurMethod;   // Just print the function out...
325 }
326
327 void 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 }