summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2001-10-15 05:51:48 +0000
committerChris Lattner <sabre@nondot.org>2001-10-15 05:51:48 +0000
commit2e42d3a3060ff0c3d4c419f17493bc6a7683e9d0 (patch)
treed796bc523341806373c120a3bfe45776b2642fa3 /lib
parent8d2de8a82cce67513debee7a3fa5aca0189b4105 (diff)
downloadexternal_llvm-2e42d3a3060ff0c3d4c419f17493bc6a7683e9d0.zip
external_llvm-2e42d3a3060ff0c3d4c419f17493bc6a7683e9d0.tar.gz
external_llvm-2e42d3a3060ff0c3d4c419f17493bc6a7683e9d0.tar.bz2
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
Diffstat (limited to 'lib')
-rw-r--r--lib/ExecutionEngine/Interpreter/Execution.cpp163
-rw-r--r--lib/ExecutionEngine/Interpreter/ExecutionAnnotations.h47
-rw-r--r--lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp30
-rw-r--r--lib/ExecutionEngine/Interpreter/Interpreter.h5
-rw-r--r--lib/ExecutionEngine/Interpreter/UserInput.cpp45
5 files changed, 252 insertions, 38 deletions
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 @@ static unsigned getOperandSlot(Value *V) {
}
#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 @@ static GenericValue getOperandValue(Value *V, ExecutionContext &SF) {
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 GenericValue getOperandValue(Value *V, ExecutionContext &SF) {
}
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 @@ void Interpreter::executeRetInst(ReturnInst *I, ExecutionContext &SF) {
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 @@ void Interpreter::executeRetInst(ReturnInst *I, ExecutionContext &SF) {
// instruction.
cout << "Method " << M->getType() << " \"" << M->getName()
<< "\" returned ";
- printValue(RetTy, Result);
+ print(RetTy, Result);
cout << endl;
}
}
@@ -341,11 +464,6 @@ void Interpreter::executeBrInst(BranchInst *I, ExecutionContext &SF) {
// 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 @@ void Interpreter::executeAllocInst(AllocationInst *I, ExecutionContext &SF) {
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 @@ unsigned MethodInfo::getValueSlot(const Value *V) {
}
-void Interpreter::initializeExecutionEngine() {
- AnnotationManager::registerAnnotationFactory(MethodInfoAID, CreateMethodInfo);
-}
-
//===----------------------------------------------------------------------===//
// callMethod - Execute the specified method...
//
@@ -703,9 +817,6 @@ void Interpreter::stepInstruction() { // Do the 'step' command
}
// --- UI Stuff...
-
-
-
void Interpreter::nextInstruction() { // Do the 'next' command
if (ECStack.empty()) {
cout << "Error: no program running, cannot 'next'!\n";
@@ -746,7 +857,6 @@ void Interpreter::run() {
if (HitBreakpoint) {
cout << "Breakpoint hit!\n";
}
-
// Print the next instruction to execute...
printCurrentInstruction();
}
@@ -787,8 +897,6 @@ void Interpreter::printCurrentInstruction() {
}
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 Type *Ty, GenericValue V) {
}
}
-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 @@ void Interpreter::infoValue(const string &Name) {
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 @@ struct MethodInfo : public Annotation {
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 @@ static AnnotationID BreakpointAID(
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 @@ void Interpreter::callExternalMethod(Method *M,
//
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 @@ GenericValue lle_Vb_putchar(MethodType *M, const vector<GenericValue> &Args) {
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 @@ public:
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 @@ 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;
@@ -118,6 +124,43 @@ void Interpreter::handleUserInput() {
} 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