Enhancements to pass argc & argv to main if required
[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 <algorithm>
12
13 enum CommandID {
14   Quit, Help,                                 // Basics
15   Print, Info, List, StackTrace, Up, Down,    // Inspection
16   Next, Step, Run, Finish, Call,              // Control flow changes
17   Break, Watch,                               // Debugging
18   Load, Flush
19 };
20
21 // CommandTable - Build a lookup table for the commands available to the user...
22 static struct CommandTableElement {
23   const char *Name;
24   enum CommandID CID;
25
26   inline bool operator<(const CommandTableElement &E) const {
27     return string(Name) < string(E.Name);
28   }
29   inline bool operator==(const string &S) const { 
30     return string(Name) == S;
31   }
32 } CommandTable[] = {
33   { "quit"     , Quit       }, { "q", Quit }, { "", Quit }, // Empty str = eof
34   { "help"     , Help       }, { "h", Help },
35
36   { "print"    , Print      }, { "p", Print },
37   { "list"     , List       },
38   { "info"     , Info       },
39   { "backtrace", StackTrace }, { "bt", StackTrace }, { "where", StackTrace },
40   { "up"       , Up         },
41   { "down"     , Down       },
42
43   { "next"     , Next       }, { "n", Next },
44   { "step"     , Step       }, { "s", Step },
45   { "run"      , Run        },
46   { "finish"   , Finish     },
47   { "call"     , Call       },
48
49   { "break"    , Break      }, { "b", Break },
50   { "watch"    , Watch      },
51
52   { "load"     , Load       },
53   { "flush"    , Flush      },
54 };
55 static CommandTableElement *CommandTableEnd = 
56    CommandTable+sizeof(CommandTable)/sizeof(CommandTable[0]);
57
58
59 //===----------------------------------------------------------------------===//
60 // handleUserInput - Enter the input loop for the interpreter.  This function
61 // returns when the user quits the interpreter.
62 //
63 void Interpreter::handleUserInput() {
64   bool UserQuit = false;
65
66   // Sort the table...
67   sort(CommandTable, CommandTableEnd);
68
69   // Print the instruction that we are stopped at...
70   printCurrentInstruction();
71
72   do {
73     string Command;
74     cout << "lli> " << flush;
75     cin >> Command;
76
77     CommandTableElement *E = find(CommandTable, CommandTableEnd, Command);
78
79     if (E == CommandTableEnd) {
80       cout << "Error: '" << Command << "' not recognized!\n";
81       continue;
82     }
83
84     switch (E->CID) {
85     case Quit:       UserQuit = true;   break;
86     case Load:
87       cin >> Command;
88       loadModule(Command);
89       break;
90     case Flush: flushModule(); break;
91     case Print:
92       cin >> Command;
93       print(Command);
94       break;
95     case Info:
96       cin >> Command;
97       infoValue(Command);
98       break;
99      
100     case List:       list();            break;
101     case StackTrace: printStackTrace(); break;
102     case Up: 
103       if (CurFrame > 0) --CurFrame;
104       else cout << "Error: Already at root of stack!\n";
105       break;
106     case Down:
107       if ((unsigned)CurFrame < ECStack.size()-1) ++CurFrame;
108       else cout << "Error: Already at bottom of stack!\n";
109       break;
110     case Next:       nextInstruction(); break;
111     case Step:       stepInstruction(); break;
112     case Run:        run();             break;
113     case Finish:     finish();          break;
114     case Call:
115       cin >> Command;
116       callMethod(Command);    // Enter the specified method
117       finish();               // Run until it's complete
118       break;
119
120     default:
121       cout << "Command '" << Command << "' unimplemented!\n";
122       break;
123     }
124
125   } while (!UserQuit);
126 }
127
128 //===----------------------------------------------------------------------===//
129 // loadModule - Load a new module to execute...
130 //
131 void Interpreter::loadModule(const string &Filename) {
132   if (CurMod && !flushModule()) return;  // Kill current execution
133
134   CurMod = ParseBytecodeFile(Filename);
135   if (CurMod == 0) {
136     cout << "Error parsing '" << Filename << "': No module loaded.\n";
137     return;
138   }
139
140   // TODO: link in support library...
141 }
142
143
144 //===----------------------------------------------------------------------===//
145 // flushModule - Return true if the current program has been unloaded.
146 //
147 bool Interpreter::flushModule() {
148   if (CurMod == 0) {
149     cout << "Error flushing: No module loaded!\n";
150     return false;
151   }
152
153   if (!ECStack.empty()) {
154     // TODO: if use is not sure, return false
155     cout << "Killing current execution!\n";
156     ECStack.clear();
157     CurFrame = -1;
158   }
159
160   delete CurMod;
161   CurMod = 0;
162   ExitCode = 0;
163   return true;
164 }
165
166 //===----------------------------------------------------------------------===//
167 // setBreakpoint - Enable a breakpoint at the specified location
168 //
169 void Interpreter::setBreakpoint(const string &Name) {
170   Value *PickedVal = ChooseOneOption(Name, LookupMatchingNames(Name));
171   // TODO: Set a breakpoint on PickedVal
172 }
173
174 //===----------------------------------------------------------------------===//
175 // callMethod - Enter the specified method...
176 //
177 bool Interpreter::callMethod(const string &Name) {
178   vector<Value*> Options = LookupMatchingNames(Name);
179
180   for (unsigned i = 0; i < Options.size(); ++i) { // Remove nonmethod matches...
181     if (!isa<Method>(Options[i])) {
182       Options.erase(Options.begin()+i);
183       --i;
184     }
185   }
186
187   Value *PickedMeth = ChooseOneOption(Name, Options);
188   if (PickedMeth == 0)
189     return true;
190
191   Method *M = cast<Method>(PickedMeth);
192
193   vector<GenericValue> Args;
194   // TODO, get args from user...
195
196   callMethod(M, Args);  // Start executing it...
197
198   // Reset the current frame location to the top of stack
199   CurFrame = ECStack.size()-1;
200
201   return false;
202 }
203
204
205 // callMainMethod - This is a nasty gross hack that will dissapear when
206 // callMethod can parse command line options and stuff for us.
207 //
208 bool Interpreter::callMainMethod(const string &Name,
209                                  const string &InputFilename) {
210   vector<Value*> Options = LookupMatchingNames(Name);
211
212   for (unsigned i = 0; i < Options.size(); ++i) { // Remove nonmethod matches...
213     if (!isa<Method>(Options[i])) {
214       Options.erase(Options.begin()+i);
215       --i;
216     }
217   }
218
219   Value *PickedMeth = ChooseOneOption(Name, Options);
220   if (PickedMeth == 0)
221     return true;
222
223   Method *M = cast<Method>(PickedMeth);
224   const MethodType *MT = M->getMethodType();
225
226   vector<GenericValue> Args;
227   switch (MT->getParamTypes().size()) {
228   default:
229     cout << "Unknown number of arguments to synthesize for '" << Name << "'!\n";
230     return true;
231   case 2: {
232     PointerType *SPP = PointerType::get(PointerType::get(Type::SByteTy));
233     if (MT->getParamTypes()[1] != SPP) {
234       cout << "Second argument of '" << Name << "' should have type: '"
235            << SPP->getDescription() << "'!\n";
236       return true;
237     }
238     // TODO:
239     GenericValue GV; GV.PointerVal = 0;
240     Args.push_back(GV);
241   }
242     // fallthrough
243   case 1:
244     if (!MT->getParamTypes()[0]->isIntegral()) {
245       cout << "First argument of '" << Name << "' should be integral!\n";
246       return true;
247     } else {
248       GenericValue GV; GV.IntVal = 1;
249       Args.insert(Args.begin(), GV);
250     }
251     // fallthrough
252   case 0:
253     break;
254   }
255
256   callMethod(M, Args);  // Start executing it...
257
258   // Reset the current frame location to the top of stack
259   CurFrame = ECStack.size()-1;
260
261   return false;
262 }