Implement global variables.  Struct and Pointer initializers are not implemented yet though


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@818 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp
index 34a80fe..668ef6d 100644
--- a/lib/ExecutionEngine/Interpreter/Execution.cpp
+++ b/lib/ExecutionEngine/Interpreter/Execution.cpp
@@ -14,6 +14,109 @@
 #include "llvm/Assembly/Writer.h"
 #include "llvm/Support/DataTypes.h"
 #include "llvm/Target/TargetData.h"
+#include "llvm/GlobalVariable.h"
+
+// Create a TargetData structure to handle memory addressing and size/alignment
+// computations
+//
+static TargetData TD("lli Interpreter");
+
+//===----------------------------------------------------------------------===//
+//                    Annotation Wrangling code
+//===----------------------------------------------------------------------===//
+
+void Interpreter::initializeExecutionEngine() {
+  AnnotationManager::registerAnnotationFactory(MethodInfoAID,
+                                               &MethodInfo::Create);
+  AnnotationManager::registerAnnotationFactory(GlobalAddressAID, 
+                                               &GlobalAddress::Create);
+}
+
+// InitializeMemory - Recursive function to apply a ConstPool value into the
+// specified memory location...
+//
+static void InitializeMemory(ConstPoolVal *Init, char *Addr) {
+#define INITIALIZE_MEMORY(TYID, CLASS, TY) \
+  case Type::TYID##TyID: {                 \
+    TY Tmp = cast<CLASS>(Init)->getValue(); \
+    memcpy(Addr, &Tmp, sizeof(TY));        \
+  } return
+
+  switch (Init->getType()->getPrimitiveID()) {
+    INITIALIZE_MEMORY(Bool   , ConstPoolBool, bool);
+    INITIALIZE_MEMORY(UByte  , ConstPoolUInt, unsigned char);
+    INITIALIZE_MEMORY(SByte  , ConstPoolSInt, signed   char);
+    INITIALIZE_MEMORY(UShort , ConstPoolUInt, unsigned short);
+    INITIALIZE_MEMORY(Short  , ConstPoolSInt, signed   short);
+    INITIALIZE_MEMORY(UInt   , ConstPoolUInt, unsigned int);
+    INITIALIZE_MEMORY(Int    , ConstPoolSInt, signed   int);
+    INITIALIZE_MEMORY(ULong  , ConstPoolUInt, uint64_t);
+    INITIALIZE_MEMORY(Long   , ConstPoolSInt,  int64_t);
+    INITIALIZE_MEMORY(Float  , ConstPoolFP  , float);
+    INITIALIZE_MEMORY(Double , ConstPoolFP  , double);
+#undef INITIALIZE_MEMORY
+  case Type::ArrayTyID: {
+    ConstPoolArray *CPA = cast<ConstPoolArray>(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<ConstPoolVal>(Val[i].get()), Addr+i*ElementSize);
+    return;
+  }
+    // TODO: Struct and Pointer!
+  case Type::StructTyID:
+  case Type::PointerTyID:
+  default:
+    cout << "Bad Type: " << Init->getType()->getDescription() << endl;
+    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<Method>(GVal)) {
+    // The GlobalAddress object for a method is just a pointer to method 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 method 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()->getValueType();  // Type to be allocated
+  unsigned NumElements = 1;
+
+  if (isa<ArrayType>(Ty) && cast<ArrayType>(Ty)->isUnsized()) {
+    assert(GV->hasInitializer() && "Const val must have an initializer!");
+    // Allocating a unsized array type?
+    Ty = cast<const ArrayType>(Ty)->getElementType();  // Get the actual type...
+
+    // Get the number of elements being allocated by the array...
+    NumElements =cast<ConstPoolArray>(GV->getInitializer())->getValues().size();
+  }
+
+  // Allocate enough memory to hold the type...
+  void *Addr = malloc(NumElements * 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
+}
+
+//===----------------------------------------------------------------------===//
+//                     Value Manipulation code
+//===----------------------------------------------------------------------===//
 
 static unsigned getOperandSlot(Value *V) {
   SlotNumber *SN = (SlotNumber*)V->getAnnotation(SlotNumberAID);
@@ -22,7 +125,7 @@
 }
 
 #define GET_CONST_VAL(TY, CLASS) \
-  case Type::TY##TyID: Result.TY##Val = ((CLASS*)CPV)->getValue(); break
+  case Type::TY##TyID: Result.TY##Val = cast<CLASS>(CPV)->getValue(); break
 
 static GenericValue getOperandValue(Value *V, ExecutionContext &SF) {
   if (ConstPoolVal *CPV = dyn_cast<ConstPoolVal>(V)) {
@@ -37,10 +140,26 @@
       GET_CONST_VAL(Int    , ConstPoolSInt);
       GET_CONST_VAL(Float  , ConstPoolFP);
       GET_CONST_VAL(Double , ConstPoolFP);
+    case Type::PointerTyID:
+      if (isa<ConstPoolPointerNull>(CPV)) {
+        Result.PointerVal = 0;
+      } else if (ConstPoolPointerReference *CPR = 
+                 dyn_cast<ConstPoolPointerReference>(CPV)) {
+        assert(0 && "Not implemented!");
+      } else {
+        assert(0 && "Unknown constant pointer type!");
+      }
+      break;
     default:
       cout << "ERROR: Constant unimp for type: " << CPV->getType() << endl;
     }
     return Result;
+  } else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
+    GlobalAddress *Address = 
+      (GlobalAddress*)GV->getOrCreateAnnotation(GlobalAddressAID);
+    GenericValue Result;
+    Result.PointerVal = (GenericValue*)Address->Ptr;
+    return Result;
   } else {
     unsigned TyP = V->getType()->getUniqueID();   // TypePlane for value
     return SF.Values[TyP][getOperandSlot(V)];
@@ -48,7 +167,11 @@
 }
 
 static void printOperandInfo(Value *V, ExecutionContext &SF) {
-  if (!isa<ConstPoolVal>(V)) {
+  if (isa<ConstPoolVal>(V)) {
+    cout << "Constant Pool Value\n";
+  } else if (isa<GlobalValue>(V)) {
+    cout << "Global Value\n";
+  } else {
     unsigned TyP  = V->getType()->getUniqueID();   // TypePlane for value
     unsigned Slot = getOperandSlot(V);
     cout << "Value=" << (void*)V << " TypeID=" << TyP << " Slot=" << Slot
@@ -294,7 +417,7 @@
     if (RetTy) {          // Nonvoid return type?
       cout << "Method " << M->getType() << " \"" << M->getName()
 	   << "\" returned ";
-      printValue(RetTy, Result);
+      print(RetTy, Result);
       cout << endl;
 
       if (RetTy->isIntegral())
@@ -319,7 +442,7 @@
     // instruction.
     cout << "Method " << M->getType() << " \"" << M->getName()
 	 << "\" returned ";
-    printValue(RetTy, Result);
+    print(RetTy, Result);
     cout << endl;
   }
 }
@@ -341,11 +464,6 @@
 //                     Memory Instruction Implementations
 //===----------------------------------------------------------------------===//
 
-// Create a TargetData structure to handle memory addressing and size/alignment
-// computations
-//
-static TargetData TD("lli Interpreter");
-
 void Interpreter::executeAllocInst(AllocationInst *I, ExecutionContext &SF) {
   const Type *Ty = I->getType()->getValueType();  // Type to be allocated
   unsigned NumElements = 1;
@@ -367,7 +485,7 @@
   SetValue(I, Result, SF);
 
   if (I->getOpcode() == Instruction::Alloca) {
-    // Keep track to free it later...
+    // TODO: FIXME: alloca should keep track of memory to free it later...
   }
 }
 
@@ -602,10 +720,6 @@
 }
 
 
-void Interpreter::initializeExecutionEngine() {
-  AnnotationManager::registerAnnotationFactory(MethodInfoAID, CreateMethodInfo);
-}
-
 //===----------------------------------------------------------------------===//
 // callMethod - Execute the specified method...
 //
@@ -703,9 +817,6 @@
 }
 
 // --- UI Stuff...
-
-
-
 void Interpreter::nextInstruction() {  // Do the 'next' command
   if (ECStack.empty()) {
     cout << "Error: no program running, cannot 'next'!\n";
@@ -746,7 +857,6 @@
   if (HitBreakpoint) {
     cout << "Breakpoint hit!\n";
   }
-
   // Print the next instruction to execute...
   printCurrentInstruction();
 }
@@ -787,8 +897,6 @@
 }
 
 void Interpreter::printValue(const Type *Ty, GenericValue V) {
-  cout << Ty << " ";
-
   switch (Ty->getPrimitiveID()) {
   case Type::BoolTyID:   cout << (V.BoolVal?"true":"false"); break;
   case Type::SByteTyID:  cout << V.SByteVal;  break;
@@ -806,15 +914,20 @@
   }
 }
 
-void Interpreter::printValue(const string &Name) {
+void Interpreter::print(const Type *Ty, GenericValue V) {
+  cout << Ty << " ";
+  printValue(Ty, V);
+}
+
+void Interpreter::print(const string &Name) {
   Value *PickedVal = ChooseOneOption(Name, LookupMatchingNames(Name));
   if (!PickedVal) return;
 
   if (const Method *M = dyn_cast<const Method>(PickedVal)) {
     cout << M;  // Print the method
   } else {      // Otherwise there should be an annotation for the slot#
-    printValue(PickedVal->getType(), 
-	       getOperandValue(PickedVal, ECStack[CurFrame]));
+    print(PickedVal->getType(), 
+          getOperandValue(PickedVal, ECStack[CurFrame]));
     cout << endl;
   }
     
@@ -825,8 +938,8 @@
   if (!PickedVal) return;
 
   cout << "Value: ";
-  printValue(PickedVal->getType(), 
-	     getOperandValue(PickedVal, ECStack[CurFrame]));
+  print(PickedVal->getType(), 
+        getOperandValue(PickedVal, ECStack[CurFrame]));
   cout << endl;
   printOperandInfo(PickedVal, ECStack[CurFrame]);
 }
diff --git a/lib/ExecutionEngine/Interpreter/ExecutionAnnotations.h b/lib/ExecutionEngine/Interpreter/ExecutionAnnotations.h
index bdcffd8..f6a2726 100644
--- a/lib/ExecutionEngine/Interpreter/ExecutionAnnotations.h
+++ b/lib/ExecutionEngine/Interpreter/ExecutionAnnotations.h
@@ -25,20 +25,19 @@
   MethodInfo(Method *M);
   vector<unsigned> NumPlaneElements;
 
+
+  // Create - Factory function to allow MethodInfo annotations to be
+  // created on demand.
+  //
+  static Annotation *Create(AnnotationID AID, const Annotable *O, void *) {
+    assert(AID == MethodInfoAID);
+    return new MethodInfo(cast<Method>((Value*)O));  // Simply invoke the ctor
+  }
+
 private:
   unsigned getValueSlot(const Value *V);
 };
 
-// CreateMethodInfo - Factory function to allow MethodInfo annotations to be
-// created on demand.
-//
-inline static Annotation *CreateMethodInfo(AnnotationID AID, const Annotable *O,
-					   void *) {
-  assert(AID == MethodInfoAID);
-  return new MethodInfo((Method*)O);  // Simply invoke the ctor
-}
-
-
 //===----------------------------------------------------------------------===//
 // Support for the SlotNumber annotation
 //===----------------------------------------------------------------------===//
@@ -89,4 +88,32 @@
 	            AnnotationManager::getID("Interpreter::Breakpoint"));
 // 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 Method's,
+// this pointer is the Method 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
diff --git a/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
index 4c2039d..7be3336 100644
--- a/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
+++ b/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
@@ -91,10 +91,32 @@
 //
 extern "C" {  // Don't add C++ manglings to llvm mangling :)
 
+// Implement void printstr([ubyte {x N}] *)
+GenericValue lle_VP_printstr(MethodType *M, const vector<GenericValue> &ArgVal){
+  assert(ArgVal.size() == 1 && "printstr only takes one argument!");
+  cout << (char*)ArgVal[0].PointerVal;
+  return GenericValue();
+}
+
 // Implement 'void print(X)' for every type...
 GenericValue lle_X_print(MethodType *M, const vector<GenericValue> &ArgVals) {
   assert(ArgVals.size() == 1 && "generic print only takes one argument!");
-  Interpreter::printValue(M->getParamTypes()[0], ArgVals[0]);
+
+  Interpreter::print(M->getParamTypes()[0], ArgVals[0]);
+  return GenericValue();
+}
+
+// Implement 'void printVal(X)' for every type...
+GenericValue lle_X_printVal(MethodType *M, const vector<GenericValue> &ArgVal) {
+  assert(ArgVal.size() == 1 && "generic print only takes one argument!");
+
+  // Specialize print([ubyte {x N} ] *)
+  if (PointerType *PTy = dyn_cast<PointerType>(M->getParamTypes()[0].get()))
+    if (const ArrayType *ATy = dyn_cast<ArrayType>(PTy->getValueType())) {
+      return lle_VP_printstr(M, ArgVal);
+    }
+
+  Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);
   return GenericValue();
 }
 
@@ -104,4 +126,10 @@
   return GenericValue();
 }
 
+// void "putchar"(ubyte)
+GenericValue lle_VB_putchar(MethodType *M, const vector<GenericValue> &Args) {
+  cout << Args[0].UByteVal;
+  return GenericValue();
+}
+
 } // End extern "C"
diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.h b/lib/ExecutionEngine/Interpreter/Interpreter.h
index e7f5c86..4b73b3d 100644
--- a/lib/ExecutionEngine/Interpreter/Interpreter.h
+++ b/lib/ExecutionEngine/Interpreter/Interpreter.h
@@ -74,10 +74,13 @@
   void handleUserInput();
 
   // User Interation Methods...
+  void loadModule(const string &Filename);
+  bool flushModule();
   bool callMethod(const string &Name);      // return true on failure
   void setBreakpoint(const string &Name);
   void infoValue(const string &Name);
-  void printValue(const string &Name);
+  void print(const string &Name);
+  static void print(const Type *Ty, GenericValue V);
   static void printValue(const Type *Ty, GenericValue V);
 
 
diff --git a/lib/ExecutionEngine/Interpreter/UserInput.cpp b/lib/ExecutionEngine/Interpreter/UserInput.cpp
index e9fc9db..4c2faf6 100644
--- a/lib/ExecutionEngine/Interpreter/UserInput.cpp
+++ b/lib/ExecutionEngine/Interpreter/UserInput.cpp
@@ -5,6 +5,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Interpreter.h"
+#include "llvm/Bytecode/Reader.h"
 #include "llvm/Assembly/Writer.h"
 #include <algorithm>
 
@@ -81,9 +82,14 @@
 
     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;
@@ -118,6 +124,43 @@
   } while (!UserQuit);
 }
 
+//===----------------------------------------------------------------------===//
+// loadModule - Load a new module to execute...
+//
+void Interpreter::loadModule(const string &Filename) {
+  if (CurMod && !flushModule()) return;  // Kill current execution
+
+  CurMod = ParseBytecodeFile(Filename);
+  if (CurMod == 0) {
+    cout << "Error parsing '" << Filename << "': No module loaded.\n";
+    return;
+  }
+
+  // TODO: link in support library...
+}
+
+
+//===----------------------------------------------------------------------===//
+// 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;
+  }
+
+  delete CurMod;
+  CurMod = 0;
+  ExitCode = 0;
+  return true;
+}
 
 //===----------------------------------------------------------------------===//
 // setBreakpoint - Enable a breakpoint at the specified location