Add support for isnan
[oota-llvm.git] / lib / ExecutionEngine / Interpreter / UserInput.cpp
index 508bd4a324691e45ce0b318ee9db108eac3738da..f0975a72d8fcccf65d39e2d0e716401c9f0fe5f6 100644 (file)
@@ -5,15 +5,21 @@
 //===----------------------------------------------------------------------===//
 
 #include "Interpreter.h"
-#include "llvm/Assembly/Writer.h"
+#include "llvm/Bytecode/Reader.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Transforms/Utils/Linker.h"
 #include <algorithm>
+using std::string;
+using std::cout;
+using std::cin;
 
 enum CommandID {
   Quit, Help,                                 // Basics
   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 +55,9 @@ static struct CommandTableElement {
 
   { "load"     , Load       },
   { "flush"    , Flush      },
+
+  { "trace"    , TraceOpt   },
+  { "profile"  , ProfileOpt },
 };
 static CommandTableElement *CommandTableEnd = 
    CommandTable+sizeof(CommandTable)/sizeof(CommandTable[0]);
@@ -62,14 +71,14 @@ void Interpreter::handleUserInput() {
   bool UserQuit = false;
 
   // Sort the table...
-  sort(CommandTable, CommandTableEnd);
+  std::sort(CommandTable, CommandTableEnd);
 
   // Print the instruction that we are stopped at...
   printCurrentInstruction();
 
   do {
     string Command;
-    cout << "lli> " << flush;
+    cout << "lli> " << std::flush;
     cin >> Command;
 
     CommandTableElement *E = find(CommandTable, CommandTableEnd, Command);
@@ -81,9 +90,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 +107,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;
@@ -106,10 +123,20 @@ void Interpreter::handleUserInput() {
     case Finish:     finish();          break;
     case Call:
       cin >> Command;
-      callMethod(Command);    // Enter the specified method
+      callMethod(Command);    // Enter the specified function
       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 +145,60 @@ 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
+
+#if 0
+  string RuntimeLib = getCurrentExecutablePath();
+  if (!RuntimeLib.empty()) RuntimeLib += "/";
+  RuntimeLib += "RuntimeLib.bc";
+
+  if (Module *SupportLib = ParseBytecodeFile(RuntimeLib, &ErrorMsg)) {
+    if (LinkModules(CurMod, SupportLib, &ErrorMsg))
+      std::cerr << "Error Linking runtime library into current module: "
+                << ErrorMsg << "\n";
+  } else {
+    std::cerr << "Error loading runtime library '"+RuntimeLib+"': "
+              << ErrorMsg << "\n";
+  }
+#endif
+}
+
+
+//===----------------------------------------------------------------------===//
+// 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
@@ -131,10 +212,10 @@ void Interpreter::setBreakpoint(const string &Name) {
 // callMethod - Enter the specified method...
 //
 bool Interpreter::callMethod(const string &Name) {
-  vector<Value*> Options = LookupMatchingNames(Name);
+  std::vector<Value*> Options = LookupMatchingNames(Name);
 
-  for (unsigned i = 0; i < Options.size(); ++i) { // Remove nonmethod matches...
-    if (!Options[i]->isMethod()) {
+  for (unsigned i = 0; i < Options.size(); ++i) { // Remove non-fn matches...
+    if (!isa<Function>(Options[i])) {
       Options.erase(Options.begin()+i);
       --i;
     }
@@ -144,11 +225,69 @@ bool Interpreter::callMethod(const string &Name) {
   if (PickedMeth == 0)
     return true;
 
-  Method *M = PickedMeth->castMethodAsserting();
+  Function *F = cast<Function>(PickedMeth);
 
-  vector<GenericValue> Args;
+  std::vector<GenericValue> Args;
   // TODO, get args from user...
 
+  callMethod(F, Args);  // Start executing it...
+
+  // Reset the current frame location to the top of stack
+  CurFrame = ECStack.size()-1;
+
+  return false;
+}
+
+// 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 std::vector<string> &InputArgv) {
+  std::vector<Value*> Options = LookupMatchingNames(Name);
+
+  for (unsigned i = 0; i < Options.size(); ++i) { // Remove non-fn matches...
+    if (!isa<Function>(Options[i])) {
+      Options.erase(Options.begin()+i);
+      --i;
+    }
+  }
+
+  Value *PickedMeth = ChooseOneOption(Name, Options);
+  if (PickedMeth == 0)
+    return true;
+
+  Function *M = cast<Function>(PickedMeth);
+  const FunctionType *MT = M->getFunctionType();
+
+  std::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;
+    }
+
+    Args.push_back(CreateArgv(InputArgv));
+  }
+    // fallthrough
+  case 1:
+    if (!MT->getParamTypes()[0]->isInteger()) {
+      cout << "First argument of '" << Name << "' should be an integer!\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
@@ -156,3 +295,20 @@ bool Interpreter::callMethod(const string &Name) {
 
   return false;
 }
+
+
+
+void Interpreter::list() {
+  if (ECStack.empty())
+    cout << "Error: No program executing!\n";
+  else
+    CW << ECStack[CurFrame].CurMethod;   // Just print the function out...
+}
+
+void Interpreter::printStackTrace() {
+  if (ECStack.empty()) cout << "No program executing!\n";
+
+  for (unsigned i = 0; i < ECStack.size(); ++i) {
+    printStackFrame((int)i);
+  }
+}