Substantial changes to refactor LLI to incorporate both the Jello JIT and
authorChris Lattner <sabre@nondot.org>
Mon, 23 Dec 2002 23:59:41 +0000 (23:59 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 23 Dec 2002 23:59:41 +0000 (23:59 +0000)
the traditional LLI interpreter

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@5125 91177308-0d34-0410-b5e6-96231b3b80d8

lib/ExecutionEngine/Interpreter/Execution.cpp
lib/ExecutionEngine/Interpreter/ExecutionAnnotations.h
lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
lib/ExecutionEngine/Interpreter/Interpreter.h
lib/ExecutionEngine/Interpreter/Support.cpp
lib/ExecutionEngine/Interpreter/UserInput.cpp
lib/ExecutionEngine/Makefile
tools/lli/Makefile
tools/lli/lli.cpp

index b400a8a82f18a1faf5fdedc4c7c35b0bf6011200..65c75635973f51ecaf5f966c1be766d01df62228 100644 (file)
@@ -6,6 +6,8 @@
 
 #include "Interpreter.h"
 #include "ExecutionAnnotations.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/Function.h"
 #include "llvm/iPHINode.h"
 #include "llvm/iOther.h"
 #include "llvm/iTerminators.h"
@@ -13,7 +15,6 @@
 #include "llvm/DerivedTypes.h"
 #include "llvm/Constants.h"
 #include "llvm/Assembly/Writer.h"
-#include "llvm/Target/TargetData.h"
 #include "Support/CommandLine.h"
 #include "Support/Statistic.h"
 #include <math.h>  // For fmod
@@ -23,11 +24,14 @@ using std::vector;
 using std::cout;
 using std::cerr;
 
+Interpreter *TheEE = 0;
+
 namespace {
   Statistic<> NumDynamicInsts("lli", "Number of dynamic instructions executed");
 
   cl::opt<bool>
-  QuietMode("quiet", cl::desc("Do not emit any non-program output"));
+  QuietMode("quiet", cl::desc("Do not emit any non-program output"),
+           cl::init(true));
 
   cl::alias 
   QuietModeA("q", cl::desc("Alias for -quiet"), cl::aliasopt(QuietMode));
@@ -43,10 +47,8 @@ namespace {
 // Create a TargetData structure to handle memory addressing and size/alignment
 // computations
 //
-TargetData TD("lli Interpreter");
 CachedWriter CW;     // Object to accelerate printing of LLVM
 
-
 #ifdef PROFILE_STRUCTURE_FIELDS
 static cl::opt<bool>
 ProfileStructureFields("profilestructfields", 
@@ -87,48 +89,12 @@ static unsigned getOperandSlot(Value *V) {
   return SN->SlotNum;
 }
 
-#define GET_CONST_VAL(TY, CLASS) \
-  case Type::TY##TyID: Result.TY##Val = cast<CLASS>(C)->getValue(); break
-
 // Operations used by constant expr implementations...
 static GenericValue executeCastOperation(Value *Src, const Type *DestTy,
                                          ExecutionContext &SF);
-static GenericValue executeGEPOperation(Value *Src, User::op_iterator IdxBegin,
-                                        User::op_iterator IdxEnd,
-                                        ExecutionContext &SF);
 static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2, 
                                   const Type *Ty, ExecutionContext &SF);
 
-static GenericValue getConstantValue(const Constant *C) {
-  GenericValue Result;
-  switch (C->getType()->getPrimitiveID()) {
-    GET_CONST_VAL(Bool   , ConstantBool);
-    GET_CONST_VAL(UByte  , ConstantUInt);
-    GET_CONST_VAL(SByte  , ConstantSInt);
-    GET_CONST_VAL(UShort , ConstantUInt);
-    GET_CONST_VAL(Short  , ConstantSInt);
-    GET_CONST_VAL(UInt   , ConstantUInt);
-    GET_CONST_VAL(Int    , ConstantSInt);
-    GET_CONST_VAL(ULong  , ConstantUInt);
-    GET_CONST_VAL(Long   , ConstantSInt);
-    GET_CONST_VAL(Float  , ConstantFP);
-    GET_CONST_VAL(Double , ConstantFP);
-  case Type::PointerTyID:
-    if (isa<ConstantPointerNull>(C)) {
-      Result.PointerVal = 0;
-    } else if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(C)){
-      GlobalAddress *Address = 
-       (GlobalAddress*)CPR->getValue()->getOrCreateAnnotation(GlobalAddressAID);
-      Result.PointerVal = (PointerTy)Address->Ptr;
-    } else {
-      assert(0 && "Unknown constant pointer type!");
-    }
-    break;
-  default:
-    cout << "ERROR: Constant unimp for type: " << C->getType() << "\n";
-  }
-  return Result;
-}
 
 static GenericValue getOperandValue(Value *V, ExecutionContext &SF) {
   if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
@@ -136,8 +102,8 @@ static GenericValue getOperandValue(Value *V, ExecutionContext &SF) {
     case Instruction::Cast:
       return executeCastOperation(CE->getOperand(0), CE->getType(), SF);
     case Instruction::GetElementPtr:
-      return executeGEPOperation(CE->getOperand(0), CE->op_begin()+1,
-                                 CE->op_end(), SF);
+      return TheEE->executeGEPOperation(CE->getOperand(0), CE->op_begin()+1,
+                                       CE->op_end(), SF);
     case Instruction::Add:
       return executeAddInst(getOperandValue(CE->getOperand(0), SF),
                             getOperandValue(CE->getOperand(1), SF),
@@ -148,13 +114,9 @@ static GenericValue getOperandValue(Value *V, ExecutionContext &SF) {
       { GenericValue V; return V; }
     }
   } else if (Constant *CPV = dyn_cast<Constant>(V)) {
-    return getConstantValue(CPV);
+    return TheEE->getConstantValue(CPV);
   } else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
-    GlobalAddress *Address = 
-      (GlobalAddress*)GV->getOrCreateAnnotation(GlobalAddressAID);
-    GenericValue Result;
-    Result.PointerVal = (PointerTy)(GenericValue*)Address->Ptr;
-    return Result;
+    return PTOGV(TheEE->getPointerToGlobal(GV));
   } else {
     unsigned TyP = V->getType()->getUniqueID();   // TypePlane for value
     unsigned OpSlot = getOperandSlot(V);
@@ -201,85 +163,12 @@ static void SetValue(Value *V, GenericValue Val, ExecutionContext &SF) {
 //===----------------------------------------------------------------------===//
 
 void Interpreter::initializeExecutionEngine() {
+  TheEE = this;
   AnnotationManager::registerAnnotationFactory(MethodInfoAID,
                                                &MethodInfo::Create);
-  AnnotationManager::registerAnnotationFactory(GlobalAddressAID, 
-                                               &GlobalAddress::Create);
   initializeSignalHandlers();
 }
 
-static void StoreValueToMemory(GenericValue Val, GenericValue *Ptr,
-                               const Type *Ty);
-
-// InitializeMemory - Recursive function to apply a Constant value into the
-// specified memory location...
-//
-static void InitializeMemory(const Constant *Init, char *Addr) {
-
-  if (Init->getType()->isFirstClassType()) {
-    GenericValue Val = getConstantValue(Init);
-    StoreValueToMemory(Val, (GenericValue*)Addr, Init->getType());
-    return;
-  }
-
-  switch (Init->getType()->getPrimitiveID()) {
-  case Type::ArrayTyID: {
-    const ConstantArray *CPA = cast<ConstantArray>(Init);
-    const vector<Use> &Val = CPA->getValues();
-    unsigned ElementSize = 
-      TD.getTypeSize(cast<ArrayType>(CPA->getType())->getElementType());
-    for (unsigned i = 0; i < Val.size(); ++i)
-      InitializeMemory(cast<Constant>(Val[i].get()), Addr+i*ElementSize);
-    return;
-  }
-
-  case Type::StructTyID: {
-    const ConstantStruct *CPS = cast<ConstantStruct>(Init);
-    const StructLayout *SL=TD.getStructLayout(cast<StructType>(CPS->getType()));
-    const vector<Use> &Val = CPS->getValues();
-    for (unsigned i = 0; i < Val.size(); ++i)
-      InitializeMemory(cast<Constant>(Val[i].get()),
-                       Addr+SL->MemberOffsets[i]);
-    return;
-  }
-
-  default:
-    CW << "Bad Type: " << Init->getType() << "\n";
-    assert(0 && "Unknown constant type to initialize memory with!");
-  }
-}
-
-Annotation *GlobalAddress::Create(AnnotationID AID, const Annotable *O, void *){
-  assert(AID == GlobalAddressAID);
-
-  // This annotation will only be created on GlobalValue objects...
-  GlobalValue *GVal = cast<GlobalValue>((Value*)O);
-
-  if (isa<Function>(GVal)) {
-    // The GlobalAddress object for a function is just a pointer to function
-    // itself.  Don't delete it when the annotation is gone though!
-    return new GlobalAddress(GVal, false);
-  }
-
-  // Handle the case of a global variable...
-  assert(isa<GlobalVariable>(GVal) && 
-         "Global value found that isn't a function or global variable!");
-  GlobalVariable *GV = cast<GlobalVariable>(GVal);
-  
-  // First off, we must allocate space for the global variable to point at...
-  const Type *Ty = GV->getType()->getElementType();  // Type to be allocated
-
-  // Allocate enough memory to hold the type...
-  void *Addr = calloc(1, TD.getTypeSize(Ty));
-  assert(Addr != 0 && "Null pointer returned by malloc!");
-
-  // Initialize the memory if there is an initializer...
-  if (GV->hasInitializer())
-    InitializeMemory(GV->getInitializer(), (char*)Addr);
-
-  return new GlobalAddress(Addr, true);  // Simply invoke the ctor
-}
-
 //===----------------------------------------------------------------------===//
 //                    Binary Instruction Implementations
 //===----------------------------------------------------------------------===//
@@ -760,8 +649,7 @@ void Interpreter::executeAllocInst(AllocationInst &I, ExecutionContext &SF) {
   // FIXME: Don't use CALLOC, use a tainted malloc.
   void *Memory = calloc(NumElements, TD.getTypeSize(Ty));
 
-  GenericValue Result;
-  Result.PointerVal = (PointerTy)Memory;
+  GenericValue Result = PTOGV(Memory);
   assert(Result.PointerVal != 0 && "Null pointer returned by malloc!");
   SetValue(&I, Result, SF);
 
@@ -773,15 +661,15 @@ static void executeFreeInst(FreeInst &I, ExecutionContext &SF) {
   assert(isa<PointerType>(I.getOperand(0)->getType()) && "Freeing nonptr?");
   GenericValue Value = getOperandValue(I.getOperand(0), SF);
   // TODO: Check to make sure memory is allocated
-  free((void*)Value.PointerVal);   // Free memory
+  free(GVTOP(Value));   // Free memory
 }
 
 
 // getElementOffset - The workhorse for getelementptr.
 //
-static GenericValue executeGEPOperation(Value *Ptr, User::op_iterator I,
-                                        User::op_iterator E,
-                                        ExecutionContext &SF) {
+GenericValue Interpreter::executeGEPOperation(Value *Ptr, User::op_iterator I,
+                                             User::op_iterator E,
+                                             ExecutionContext &SF) {
   assert(isa<PointerType>(Ptr->getType()) &&
          "Cannot getElementOffset of a nonpointer type!");
 
@@ -834,13 +722,13 @@ static GenericValue executeGEPOperation(Value *Ptr, User::op_iterator I,
 }
 
 static void executeGEPInst(GetElementPtrInst &I, ExecutionContext &SF) {
-  SetValue(&I, executeGEPOperation(I.getPointerOperand(),
+  SetValue(&I, TheEE->executeGEPOperation(I.getPointerOperand(),
                                    I.idx_begin(), I.idx_end(), SF), SF);
 }
 
-static void executeLoadInst(LoadInst &I, ExecutionContext &SF) {
+void Interpreter::executeLoadInst(LoadInst &I, ExecutionContext &SF) {
   GenericValue SRC = getOperandValue(I.getPointerOperand(), SF);
-  GenericValue *Ptr = (GenericValue*)SRC.PointerVal;
+  GenericValue *Ptr = (GenericValue*)GVTOP(SRC);
   GenericValue Result;
 
   if (TD.isLittleEndian()) {
@@ -910,102 +798,14 @@ static void executeLoadInst(LoadInst &I, ExecutionContext &SF) {
   SetValue(&I, Result, SF);
 }
 
-static void StoreValueToMemory(GenericValue Val, GenericValue *Ptr,
-                               const Type *Ty) {
-  if (TD.isLittleEndian()) {
-    switch (Ty->getPrimitiveID()) {
-    case Type::BoolTyID:
-    case Type::UByteTyID:
-    case Type::SByteTyID:   Ptr->Untyped[0] = Val.UByteVal; break;
-    case Type::UShortTyID:
-    case Type::ShortTyID:   Ptr->Untyped[0] = Val.UShortVal & 255;
-                            Ptr->Untyped[1] = (Val.UShortVal >> 8) & 255;
-                            break;
-    case Type::FloatTyID:
-    case Type::UIntTyID:
-    case Type::IntTyID:     Ptr->Untyped[0] =  Val.UIntVal        & 255;
-                            Ptr->Untyped[1] = (Val.UIntVal >>  8) & 255;
-                            Ptr->Untyped[2] = (Val.UIntVal >> 16) & 255;
-                            Ptr->Untyped[3] = (Val.UIntVal >> 24) & 255;
-                            break;
-    case Type::DoubleTyID:
-    case Type::ULongTyID:
-    case Type::LongTyID:    
-    case Type::PointerTyID: Ptr->Untyped[0] =  Val.ULongVal        & 255;
-                            Ptr->Untyped[1] = (Val.ULongVal >>  8) & 255;
-                            Ptr->Untyped[2] = (Val.ULongVal >> 16) & 255;
-                            Ptr->Untyped[3] = (Val.ULongVal >> 24) & 255;
-                            Ptr->Untyped[4] = (Val.ULongVal >> 32) & 255;
-                            Ptr->Untyped[5] = (Val.ULongVal >> 40) & 255;
-                            Ptr->Untyped[6] = (Val.ULongVal >> 48) & 255;
-                            Ptr->Untyped[7] = (Val.ULongVal >> 56) & 255;
-                            break;
-    default:
-      cout << "Cannot store value of type " << Ty << "!\n";
-    }
-  } else {
-    switch (Ty->getPrimitiveID()) {
-    case Type::BoolTyID:
-    case Type::UByteTyID:
-    case Type::SByteTyID:   Ptr->Untyped[0] = Val.UByteVal; break;
-    case Type::UShortTyID:
-    case Type::ShortTyID:   Ptr->Untyped[1] = Val.UShortVal & 255;
-                            Ptr->Untyped[0] = (Val.UShortVal >> 8) & 255;
-                            break;
-    case Type::FloatTyID:
-    case Type::UIntTyID:
-    case Type::IntTyID:     Ptr->Untyped[3] =  Val.UIntVal        & 255;
-                            Ptr->Untyped[2] = (Val.UIntVal >>  8) & 255;
-                            Ptr->Untyped[1] = (Val.UIntVal >> 16) & 255;
-                            Ptr->Untyped[0] = (Val.UIntVal >> 24) & 255;
-                            break;
-    case Type::DoubleTyID:
-    case Type::ULongTyID:
-    case Type::LongTyID:    
-    case Type::PointerTyID: Ptr->Untyped[7] =  Val.ULongVal        & 255;
-                            Ptr->Untyped[6] = (Val.ULongVal >>  8) & 255;
-                            Ptr->Untyped[5] = (Val.ULongVal >> 16) & 255;
-                            Ptr->Untyped[4] = (Val.ULongVal >> 24) & 255;
-                            Ptr->Untyped[3] = (Val.ULongVal >> 32) & 255;
-                            Ptr->Untyped[2] = (Val.ULongVal >> 40) & 255;
-                            Ptr->Untyped[1] = (Val.ULongVal >> 48) & 255;
-                            Ptr->Untyped[0] = (Val.ULongVal >> 56) & 255;
-                            break;
-    default:
-      cout << "Cannot store value of type " << Ty << "!\n";
-    }
-  }
-}
-
-static void executeStoreInst(StoreInst &I, ExecutionContext &SF) {
+void Interpreter::executeStoreInst(StoreInst &I, ExecutionContext &SF) {
   GenericValue Val = getOperandValue(I.getOperand(0), SF);
   GenericValue SRC = getOperandValue(I.getPointerOperand(), SF);
-  StoreValueToMemory(Val, (GenericValue *)SRC.PointerVal,
+  StoreValueToMemory(Val, (GenericValue *)GVTOP(SRC),
                      I.getOperand(0)->getType());
 }
 
 
-GenericValue Interpreter::CreateArgv(const std::vector<std::string> &InputArgv){
-  // Pointers are 64 bits...
-  PointerTy *Result = new PointerTy[InputArgv.size()+1];  // 64 bit assumption
-
-  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;
-
-    GenericValue GV; GV.PointerVal = (PointerTy)Dest;
-    // Endian safe: Result[i] = (PointerTy)Dest;
-    StoreValueToMemory(GV, (GenericValue*)(Result+i),
-                       Type::LongTy);  // 64 bit assumption
-  }
-
-  Result[InputArgv.size()] = 0;
-  GenericValue GV; GV.PointerVal = (PointerTy)Result;
-  return GV;
-}
-
 
 //===----------------------------------------------------------------------===//
 //                 Miscellaneous Instruction Implementations
@@ -1022,7 +822,7 @@ void Interpreter::executeCallInst(CallInst &I, ExecutionContext &SF) {
   // and treat it as a function pointer.
   GenericValue SRC = getOperandValue(I.getCalledValue(), SF);
   
-  callMethod((Function*)SRC.PointerVal, ArgVals);
+  callMethod((Function*)GVTOP(SRC), ArgVals);
 }
 
 static void executePHINode(PHINode &I, ExecutionContext &SF) {
@@ -1433,7 +1233,7 @@ void Interpreter::printValue(const Type *Ty, GenericValue V) {
   case Type::ULongTyID:  cout << (unsigned long)V.ULongVal;  break;
   case Type::FloatTyID:  cout << V.FloatVal;  break;
   case Type::DoubleTyID: cout << V.DoubleVal; break;
-  case Type::PointerTyID:cout << (void*)V.PointerVal; break;
+  case Type::PointerTyID:cout << (void*)GVTOP(V); break;
   default:
     cout << "- Don't know how to print value of this type!";
     break;
index 913e8615957533f0f34245187f4740b0c7104461..1a5c7fee9803ae0418d32733c3942c0698d91815 100644 (file)
@@ -90,32 +90,4 @@ static AnnotationID BreakpointAID(
 // Just use an Annotation directly, Breakpoint is currently just a marker
 
 
-//===----------------------------------------------------------------------===//
-// Support for the GlobalAddress annotation
-//===----------------------------------------------------------------------===//
-
-// This annotation (attached only to GlobalValue objects) is used to hold the
-// address of the chunk of memory that represents a global value.  For
-// Functions, this pointer is the Function object pointer that represents it.
-// For global variables, this is the dynamically allocated (and potentially
-// initialized) chunk of memory for the global.  This annotation is created on
-// demand.
-//
-static AnnotationID GlobalAddressAID(
-                   AnnotationManager::getID("Interpreter::GlobalAddress"));
-
-struct GlobalAddress : public Annotation {
-  void *Ptr;   // The pointer itself
-  bool Delete; // Should I delete them memory on destruction?
-
-  GlobalAddress(void *ptr, bool d) : Annotation(GlobalAddressAID), Ptr(ptr), 
-                                     Delete(d) {}
-  ~GlobalAddress() { if (Delete) free(Ptr); }
-  
-  // Create - Factory function to allow GlobalAddress annotations to be
-  // created on demand.
-  //
-  static Annotation *Create(AnnotationID AID, const Annotable *O, void *);
-};
-
 #endif
index 79e730f0ece26dcb78d57f912ced702c30e3a9cf..0d8cae2fea1c13019cb43dc464a6fc0e15a148a5 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "Interpreter.h"
 #include "ExecutionAnnotations.h"
+#include "llvm/Module.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/SymbolTable.h"
 #include "llvm/Target/TargetData.h"
@@ -23,8 +24,6 @@
 using std::vector;
 using std::cout;
 
-extern TargetData TD;
-
 typedef GenericValue (*ExFunc)(FunctionType *, const vector<GenericValue> &);
 static std::map<const Function *, ExFunc> Functions;
 static std::map<std::string, ExFunc> FuncNames;
@@ -440,8 +439,8 @@ static FILE *getFILE(PointerTy Ptr) {
   static PointerTy IOBBase = 0;
   static unsigned FILESize;
 
-  if (LastMod != TheInterpreter->getModule()) {  // Module change or initialize?
-    Module *M = LastMod = TheInterpreter->getModule();
+  if (LastMod != &TheInterpreter->getModule()) { // Module change or initialize?
+    Module *M = LastMod = &TheInterpreter->getModule();
 
     // Check to see if the currently loaded module contains an __iob symbol...
     GlobalVariable *IOB = 0;
@@ -456,6 +455,7 @@ static FILE *getFILE(PointerTy Ptr) {
       if (IOB) break;
     }
 
+#if 0   /// FIXME!  __iob support for LLI
     // If we found an __iob symbol now, find out what the actual address it's
     // held in is...
     if (IOB) {
@@ -472,6 +472,7 @@ static FILE *getFILE(PointerTy Ptr) {
       else
         FILESize = 16*8;  // Default size
     }
+#endif
   }
 
   // Check to see if this is a reference to __iob...
index c0d8b75aca508129300ab6321f228e0c4a9981c9..586828a1d14be730453502c47859865cc4b013f8 100644 (file)
 // Uncomment this line to enable profiling of structure field accesses.
 //#define PROFILE_STRUCTURE_FIELDS 1
 
-#include "llvm/Module.h"
+#include "../ExecutionEngine.h"
 #include "Support/DataTypes.h"
 #include "llvm/Assembly/CachedWriter.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/BasicBlock.h"
+#include "../GenericValue.h"
 
-extern CachedWriter CW;     // Object to accellerate printing of LLVM
+extern CachedWriter CW;     // Object to accelerate printing of LLVM
 
 struct MethodInfo;          // Defined in ExecutionAnnotations.h
 class CallInst;
 class ReturnInst;
 class BranchInst;
+class LoadInst;
+class StoreInst;
 class AllocationInst;
 
-typedef uint64_t PointerTy;
-
-union GenericValue {
-  bool            BoolVal;
-  unsigned char   UByteVal;
-  signed   char   SByteVal;
-  unsigned short  UShortVal;
-  signed   short  ShortVal;
-  unsigned int    UIntVal;
-  signed   int    IntVal;
-  uint64_t        ULongVal;
-  int64_t         LongVal;
-  double          DoubleVal;
-  float           FloatVal;
-  PointerTy       PointerVal;
-  unsigned char   Untyped[8];
-};
-
 // AllocaHolder - Object to track all of the blocks of memory allocated by
 // alloca.  When the function returns, this object is poped off the execution
 // stack, which causes the dtor to be run, which frees all the alloca'd memory.
@@ -90,25 +77,31 @@ struct ExecutionContext {
 
 // Interpreter - This class represents the entirety of the interpreter.
 //
-class Interpreter {
-  Module *CurMod;              // The current Module being executed (0 if none)
+class Interpreter : public ExecutionEngine {
   int ExitCode;                // The exit code to be returned by the lli util
+  bool Debug;                  // Debug mode enabled?
   bool Profile;                // Profiling enabled?
   bool Trace;                  // Tracing enabled?
   int CurFrame;                // The current stack frame being inspected
+  TargetData TD;
 
   // The runtime stack of executing code.  The top of the stack is the current
   // function record.
   std::vector<ExecutionContext> ECStack;
 
 public:
-  Interpreter();
-  inline ~Interpreter() { CW.setModule(0); delete CurMod; }
+  Interpreter(Module *M, unsigned Config, bool DebugMode, bool TraceMode);
+  inline ~Interpreter() { CW.setModule(0); }
 
   // getExitCode - return the code that should be the exit code for the lli
   // utility.
   inline int getExitCode() const { return ExitCode; }
-  inline Module *getModule() const { return CurMod; }
+
+  /// run - Start execution with the specified function and arguments.
+  ///
+  virtual int run(const std::string &FnName,
+                 const std::vector<std::string> &Args);
 
   // enableProfiling() - Turn profiling on, clear stats?
   void enableProfiling() { Profile = true; }
@@ -117,8 +110,6 @@ public:
   void handleUserInput();
 
   // User Interation Methods...
-  void loadModule(const std::string &Filename);
-  bool flushModule();
   bool callMethod(const std::string &Name);      // return true on failure
   void setBreakpoint(const std::string &Name);
   void infoValue(const std::string &Name);
@@ -128,7 +119,6 @@ public:
 
   bool callMainMethod(const std::string &MainName,
                       const std::vector<std::string> &InputFilename);
-  GenericValue CreateArgv(const std::vector<std::string> &InputArgv);
 
   void list();             // Do the 'list' command
   void printStackTrace();  // Do the 'backtrace' command
@@ -161,7 +151,17 @@ public:
   //
   inline bool isStopped() const { return !ECStack.empty(); }
 
+  //FIXME: private:
+public:
+  GenericValue executeGEPOperation(Value *Ptr, User::op_iterator I,
+                                  User::op_iterator E, ExecutionContext &SF);
+  void executeLoadInst(LoadInst &I, ExecutionContext &SF);
+  void executeStoreInst(StoreInst &I, ExecutionContext &SF);
+
+
 private:  // Helper functions
+  void *getPointerToFunction(const Function *F) { return (void*)F; }
+
   // getCurrentExecutablePath() - Return the directory that the lli executable
   // lives in.
   //
index 4c31d2692ad5299d8c694a1d8e8c28c21dc631e3..5f4137ce5d914ac475a94faf0beea9f5c9eaf00c 100644 (file)
@@ -7,6 +7,7 @@
 #include "Interpreter.h"
 #include "llvm/SymbolTable.h"
 #include "llvm/Assembly/Writer.h"
+#include "llvm/Module.h"
 #include <iostream>
 using std::cout;
 
@@ -38,7 +39,7 @@ std::vector<Value*> Interpreter::LookupMatchingNames(const std::string &Name) {
   Function *CurMeth = getCurrentMethod();
   
   if (CurMeth) ::LookupMatchingNames(Name, CurMeth->getSymbolTable(), Results);
-  if (CurMod ) ::LookupMatchingNames(Name, CurMod ->getSymbolTable(), Results);
+  ::LookupMatchingNames(Name, getModule().getSymbolTable(), Results);
   return Results;
 }
 
index f0975a72d8fcccf65d39e2d0e716401c9f0fe5f6..3d2b1de60a45464f9c1b05a5148d2a232b3891d3 100644 (file)
@@ -7,6 +7,7 @@
 #include "Interpreter.h"
 #include "llvm/Bytecode/Reader.h"
 #include "llvm/DerivedTypes.h"
+#include "llvm/Function.h"
 #include "llvm/Transforms/Utils/Linker.h"
 #include <algorithm>
 using std::string;
@@ -18,8 +19,8 @@ enum CommandID {
   Print, Info, List, StackTrace, Up, Down,    // Inspection
   Next, Step, Run, Finish, Call,              // Control flow changes
   Break, Watch,                               // Debugging
-  Load, Flush,
-  TraceOpt, ProfileOpt                              // Toggle features
+  Flush,
+  TraceOpt,                                   // Toggle features
 };
 
 // CommandTable - Build a lookup table for the commands available to the user...
@@ -53,11 +54,9 @@ static struct CommandTableElement {
   { "break"    , Break      }, { "b", Break },
   { "watch"    , Watch      },
 
-  { "load"     , Load       },
   { "flush"    , Flush      },
 
   { "trace"    , TraceOpt   },
-  { "profile"  , ProfileOpt },
 };
 static CommandTableElement *CommandTableEnd = 
    CommandTable+sizeof(CommandTable)/sizeof(CommandTable[0]);
@@ -90,11 +89,6 @@ 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;
       print(Command);
@@ -132,11 +126,6 @@ void Interpreter::handleUserInput() {
       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;
@@ -145,61 +134,6 @@ 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
 //
@@ -272,7 +206,7 @@ bool Interpreter::callMainMethod(const string &Name,
       return true;
     }
 
-    Args.push_back(CreateArgv(InputArgv));
+    Args.push_back(PTOGV(CreateArgv(InputArgv)));
   }
     // fallthrough
   case 1:
index a0e73d715001191f7fc267b10d454f324e977ca0..c31fb5e2da26cb3fc8babe3412cb35eb0bfa6dbc 100644 (file)
@@ -1,6 +1,10 @@
 LEVEL = ../..
 TOOLNAME = lli
-USEDLIBS = bcreader vmcore analysis.a support.a target.a transforms.a
+PARALLEL_DIRS = Interpreter JIT
+
+JITLIBS  = lli-jit codegen x86 scalaropts.a
+USEDLIBS = lli-interpreter $(JITLIBS) bcreader vmcore analysis.a support.a target.a 
+#transforms.a
 
 # Have gcc tell the linker to export symbols from the program so that
 # dynamically loaded modules can be linked against them.
index a0e73d715001191f7fc267b10d454f324e977ca0..c31fb5e2da26cb3fc8babe3412cb35eb0bfa6dbc 100644 (file)
@@ -1,6 +1,10 @@
 LEVEL = ../..
 TOOLNAME = lli
-USEDLIBS = bcreader vmcore analysis.a support.a target.a transforms.a
+PARALLEL_DIRS = Interpreter JIT
+
+JITLIBS  = lli-jit codegen x86 scalaropts.a
+USEDLIBS = lli-interpreter $(JITLIBS) bcreader vmcore analysis.a support.a target.a 
+#transforms.a
 
 # Have gcc tell the linker to export symbols from the program so that
 # dynamically loaded modules can be linked against them.
index 3f718e599e872468357207573a8d9302f79c701c..be6ed11794fc18108edb6d152b892d62d66be12d 100644 (file)
-//===----------------------------------------------------------------------===//
-// LLVM INTERPRETER/DEBUGGER/PROFILER UTILITY 
+//===- lli.cpp - LLVM Interpreter / Dynamic compiler ----------------------===//
 //
-// This utility is an interactive frontend to almost all other LLVM
-// functionality.  It may be used as an interpreter to run code, a debugger to
-// find problems, or a profiler to analyze execution frequencies.
+// This utility provides a way to execute LLVM bytecode without static
+// compilation.  This consists of a very simple and slow (but portable)
+// interpreter, along with capability for system specific dynamic compilers.  At
+// runtime, the fastest (stable) execution engine is selected to run the
+// program.  This means the JIT compiler for the current platform if it's
+// available.
 //
 //===----------------------------------------------------------------------===//
 
-#include "Interpreter.h"
+#include "ExecutionEngine.h"
 #include "Support/CommandLine.h"
+#include "llvm/Bytecode/Reader.h"
+#include "llvm/Module.h"
+#include "llvm/Target/TargetMachineImpls.h"
 
-static cl::opt<std::string>
-InputFile(cl::desc("<input bytecode>"), cl::Positional, cl::init("-"));
-
-static cl::list<std::string>
-InputArgv(cl::ConsumeAfter, cl::desc("<program arguments>..."));
+namespace {
+  cl::opt<std::string>
+  InputFile(cl::desc("<input bytecode>"), cl::Positional, cl::init("-"));
 
-static cl::opt<std::string>
-MainFunction ("f", cl::desc("Function to execute"), cl::init("main"),
-              cl::value_desc("function name"));
+  cl::list<std::string>
+  InputArgv(cl::ConsumeAfter, cl::desc("<program arguments>..."));
 
-static cl::opt<bool>
-DebugMode("d", cl::desc("Start program in debugger"));
+  cl::opt<std::string>
+  MainFunction ("f", cl::desc("Function to execute"), cl::init("main"),
+               cl::value_desc("function name"));
 
-static cl::opt<bool>
-TraceMode("trace", cl::desc("Enable Tracing"));
+  cl::opt<bool> DebugMode("d", cl::desc("Start program in debugger"));
 
-static cl::opt<bool>
-ProfileMode("profile", cl::desc("Enable Profiling [unimp]"));
+  cl::opt<bool> TraceMode("trace", cl::desc("Enable Tracing"));
 
+  cl::opt<bool> ForceInterpreter("force-interpreter",
+                                cl::desc("Force interpretation: disable JIT"),
+                                cl::init(true));
+}
 
 //===----------------------------------------------------------------------===//
-// Interpreter ctor - Initialize stuff
+// ExecutionEngine Class Implementation
 //
-Interpreter::Interpreter() : ExitCode(0), Profile(ProfileMode), 
-                             Trace(TraceMode), CurFrame(-1) {
-  CurMod = 0;
-  loadModule(InputFile);
-
-  // Initialize the "backend"
-  initializeExecutionEngine();
-  initializeExternalMethods();
+
+ExecutionEngine::~ExecutionEngine() {
+  delete &CurMod;
 }
 
 //===----------------------------------------------------------------------===//
 // main Driver function
 //
 int main(int argc, char** argv) {
-  cl::ParseCommandLineOptions(argc, argv, " llvm interpreter\n");
+  cl::ParseCommandLineOptions(argc, argv,
+                             " llvm interpreter & dynamic compiler\n");
+
+  // Load the bytecode...
+  string ErrorMsg;
+  Module *M = ParseBytecodeFile(InputFile, &ErrorMsg);
+  if (M == 0) {
+    cout << "Error parsing '" << InputFile << "': "
+         << ErrorMsg << "\n";
+    exit(1);
+  }
+
+#if 0
+  // Link in the runtime library for LLI...
+  string RuntimeLib = getCurrentExecutablePath();
+  if (!RuntimeLib.empty()) RuntimeLib += "/";
+  RuntimeLib += "RuntimeLib.bc";
+
+  if (Module *SupportLib = ParseBytecodeFile(RuntimeLib, &ErrorMsg)) {
+    if (LinkModules(M, SupportLib, &ErrorMsg))
+      std::cerr << "Error Linking runtime library into current module: "
+                << ErrorMsg << "\n";
+  } else {
+    std::cerr << "Error loading runtime library '"+RuntimeLib+"': "
+              << ErrorMsg << "\n";
+  }
+#endif
+
+  // FIXME: This should look at the PointerSize and endianness of the bytecode
+  // file to determine the endianness and pointer size of target machine to use.
+  unsigned Config = TM::PtrSize64 | TM::BigEndian;
+
+  ExecutionEngine *EE = 0;
+
+  // If there is nothing that is forcing us to use the interpreter, make a JIT.
+  if (!ForceInterpreter && !DebugMode && !TraceMode)
+    EE = ExecutionEngine::createJIT(M, Config);
+
+  // If we can't make a JIT, make an interpreter instead.
+  if (EE == 0)
+    EE = ExecutionEngine::createInterpreter(M, Config, DebugMode, TraceMode);
 
   // Add the module name to the start of the argv vector...
-  //
   InputArgv.insert(InputArgv.begin(), InputFile);
 
-  // Create the interpreter...
-  Interpreter I;
-
-  // Handle alternate names of the program.  If started as llp, enable profiling
-  // if started as ldb, enable debugging...
-  //
-  if (argv[0] == "ldb")       // TODO: Obviously incorrect, but you get the idea
-    DebugMode = true;
-  else if (argv[0] == "llp")
-    ProfileMode = true;
-
-  // If running with the profiler, enable it now...
-  if (ProfileMode) I.enableProfiling();
-  if (TraceMode) I.enableTracing();
-
-  // Start interpreter into the main function...
-  //
-  if (!I.callMainMethod(MainFunction, InputArgv) && !DebugMode) {
-    // If not in debug mode and if the call succeeded, run the code now...
-    I.run();
-  }
-
-  // If debug mode, allow the user to interact... also, if the user pressed 
-  // ctrl-c or execution hit an error, enter the event loop...
-  if (DebugMode || I.isStopped())
-    I.handleUserInput();
+  // Run the main function!
+  int ExitCode = EE->run(MainFunction, InputArgv);
 
-  // Return the status code of the program executed...
-  return I.getExitCode();
+  // Now that we are done executing the program, shut down the execution engine
+  delete EE;
+  return ExitCode;
 }