Rename ConstPoolVal -> Constant
[oota-llvm.git] / lib / ExecutionEngine / Interpreter / UserInput.cpp
index f0c7fe1b6b8fa25802b22643cf620a72db85201c..179b97d277fb321263b40f2a8c33b7c7ecf6736f 100644 (file)
@@ -5,7 +5,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "Interpreter.h"
+#include "llvm/Bytecode/Reader.h"
 #include "llvm/Assembly/Writer.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Transforms/Linker.h"
 #include <algorithm>
 
 enum CommandID {
@@ -13,7 +16,8 @@ enum CommandID {
   Print, Info, List, StackTrace, Up, Down,    // Inspection
   Next, Step, Run, Finish, Call,              // Control flow changes
   Break, Watch,                               // Debugging
-  Load, Flush
+  Load, Flush,
+  TraceOpt, ProfileOpt                              // Toggle features
 };
 
 // CommandTable - Build a lookup table for the commands available to the user...
@@ -49,6 +53,9 @@ static struct CommandTableElement {
 
   { "load"     , Load       },
   { "flush"    , Flush      },
+
+  { "trace"    , TraceOpt   },
+  { "profile"  , ProfileOpt },
 };
 static CommandTableElement *CommandTableEnd = 
    CommandTable+sizeof(CommandTable)/sizeof(CommandTable[0]);
@@ -81,9 +88,14 @@ void Interpreter::handleUserInput() {
 
     switch (E->CID) {
     case Quit:       UserQuit = true;   break;
+    case Load:
+      cin >> Command;
+      loadModule(Command);
+      break;
+    case Flush: flushModule(); break;
     case Print:
       cin >> Command;
-      printValue(Command);
+      print(Command);
       break;
     case Info:
       cin >> Command;
@@ -93,12 +105,15 @@ void Interpreter::handleUserInput() {
     case List:       list();            break;
     case StackTrace: printStackTrace(); break;
     case Up: 
-      if (CurFrame > 0) --CurFrame;
+      if (CurFrame > 0) { --CurFrame; printStackFrame(); }
       else cout << "Error: Already at root of stack!\n";
       break;
     case Down:
-      if ((unsigned)CurFrame < ECStack.size()-1) ++CurFrame;
-      else cout << "Error: Already at bottom of stack!\n";
+      if ((unsigned)CurFrame < ECStack.size()-1) {
+        ++CurFrame;
+        printStackFrame();
+      } else
+        cout << "Error: Already at bottom of stack!\n";
       break;
     case Next:       nextInstruction(); break;
     case Step:       stepInstruction(); break;
@@ -110,6 +125,16 @@ void Interpreter::handleUserInput() {
       finish();               // Run until it's complete
       break;
 
+    case TraceOpt:
+      Trace = !Trace;
+      cout << "Tracing " << (Trace ? "enabled\n" : "disabled\n");
+      break;
+
+    case ProfileOpt:
+      Profile = !Profile;
+      cout << "Profiling " << (Trace ? "enabled\n" : "disabled\n");
+      break;
+
     default:
       cout << "Command '" << Command << "' unimplemented!\n";
       break;
@@ -118,6 +143,58 @@ void Interpreter::handleUserInput() {
   } while (!UserQuit);
 }
 
+//===----------------------------------------------------------------------===//
+// loadModule - Load a new module to execute...
+//
+void Interpreter::loadModule(const string &Filename) {
+  string ErrorMsg;
+  if (CurMod && !flushModule()) return;  // Kill current execution
+
+  CurMod = ParseBytecodeFile(Filename, &ErrorMsg);
+  if (CurMod == 0) {
+    cout << "Error parsing '" << Filename << "': No module loaded: "
+         << ErrorMsg << "\n";
+    return;
+  }
+  CW.setModule(CurMod);  // Update Writer
+
+  string RuntimeLib = getCurrentExecutablePath();
+  if (!RuntimeLib.empty()) RuntimeLib += "/";
+  RuntimeLib += "RuntimeLib.bc";
+
+  if (Module *SupportLib = ParseBytecodeFile(RuntimeLib, &ErrorMsg)) {
+    if (LinkModules(CurMod, SupportLib, &ErrorMsg))
+      cerr << "Error Linking runtime library into current module: "
+           << ErrorMsg << endl;
+  } else {
+    cerr << "Error loading runtime library '"+RuntimeLib+"': "
+         << ErrorMsg << "\n";
+  }
+}
+
+
+//===----------------------------------------------------------------------===//
+// flushModule - Return true if the current program has been unloaded.
+//
+bool Interpreter::flushModule() {
+  if (CurMod == 0) {
+    cout << "Error flushing: No module loaded!\n";
+    return false;
+  }
+
+  if (!ECStack.empty()) {
+    // TODO: if use is not sure, return false
+    cout << "Killing current execution!\n";
+    ECStack.clear();
+    CurFrame = -1;
+  }
+
+  CW.setModule(0);
+  delete CurMod;
+  CurMod = 0;
+  ExitCode = 0;
+  return true;
+}
 
 //===----------------------------------------------------------------------===//
 // setBreakpoint - Enable a breakpoint at the specified location
@@ -134,7 +211,55 @@ bool Interpreter::callMethod(const string &Name) {
   vector<Value*> Options = LookupMatchingNames(Name);
 
   for (unsigned i = 0; i < Options.size(); ++i) { // Remove nonmethod matches...
-    if (!Options[i]->isMethod()) {
+    if (!isa<Method>(Options[i])) {
+      Options.erase(Options.begin()+i);
+      --i;
+    }
+  }
+
+  Value *PickedMeth = ChooseOneOption(Name, Options);
+  if (PickedMeth == 0)
+    return true;
+
+  Method *M = cast<Method>(PickedMeth);
+
+  vector<GenericValue> Args;
+  // TODO, get args from user...
+
+  callMethod(M, Args);  // Start executing it...
+
+  // Reset the current frame location to the top of stack
+  CurFrame = ECStack.size()-1;
+
+  return false;
+}
+
+static void *CreateArgv(const vector<string> &InputArgv) {
+  // Pointers are 64 bits...
+  uint64_t *Result = new PointerTy[InputArgv.size()+1];
+
+  for (unsigned i = 0; i < InputArgv.size(); ++i) {
+    unsigned Size = InputArgv[i].size()+1;
+    char *Dest = new char[Size];
+    copy(InputArgv[i].begin(), InputArgv[i].end(), Dest);
+    Dest[Size-1] = 0;
+    Result[i] = (PointerTy)Dest;
+  }
+
+  Result[InputArgv.size()] = 0;
+  return Result;
+}
+
+
+// callMainMethod - This is a nasty gross hack that will dissapear when
+// callMethod can parse command line options and stuff for us.
+//
+bool Interpreter::callMainMethod(const string &Name,
+                                 const vector<string> &InputArgv) {
+  vector<Value*> Options = LookupMatchingNames(Name);
+
+  for (unsigned i = 0; i < Options.size(); ++i) { // Remove nonmethod matches...
+    if (!isa<Method>(Options[i])) {
       Options.erase(Options.begin()+i);
       --i;
     }
@@ -144,10 +269,60 @@ bool Interpreter::callMethod(const string &Name) {
   if (PickedMeth == 0)
     return true;
 
-  callMethod(PickedMeth->castMethodAsserting());  // Start executing it...
+  Method *M = cast<Method>(PickedMeth);
+  const MethodType *MT = M->getMethodType();
+
+  vector<GenericValue> Args;
+  switch (MT->getParamTypes().size()) {
+  default:
+    cout << "Unknown number of arguments to synthesize for '" << Name << "'!\n";
+    return true;
+  case 2: {
+    PointerType *SPP = PointerType::get(PointerType::get(Type::SByteTy));
+    if (MT->getParamTypes()[1] != SPP) {
+      CW << "Second argument of '" << Name << "' should have type: '"
+         << SPP << "'!\n";
+      return true;
+    }
+
+    GenericValue GV; GV.PointerVal = (uint64_t)CreateArgv(InputArgv);
+    Args.push_back(GV);
+  }
+    // fallthrough
+  case 1:
+    if (!MT->getParamTypes()[0]->isIntegral()) {
+      cout << "First argument of '" << Name << "' should be integral!\n";
+      return true;
+    } else {
+      GenericValue GV; GV.UIntVal = InputArgv.size();
+      Args.insert(Args.begin(), GV);
+    }
+    // fallthrough
+  case 0:
+    break;
+  }
+
+  callMethod(M, Args);  // Start executing it...
 
   // Reset the current frame location to the top of stack
   CurFrame = ECStack.size()-1;
 
   return false;
 }
+
+
+
+void Interpreter::list() {
+  if (ECStack.empty())
+    cout << "Error: No program executing!\n";
+  else
+    CW << ECStack[CurFrame].CurMethod;   // Just print the method out...
+}
+
+void Interpreter::printStackTrace() {
+  if (ECStack.empty()) cout << "No program executing!\n";
+
+  for (unsigned i = 0; i < ECStack.size(); ++i) {
+    printStackFrame((int)i);
+  }
+}