//===-- Execution.cpp - Implement code to simulate the program ------------===//
//
// This file contains the actual instruction interpreter.
//
//===----------------------------------------------------------------------===//
#include "Interpreter.h"
#include "ExecutionAnnotations.h"
#include "llvm/iOther.h"
#include "llvm/iTerminators.h"
#include "llvm/iMemory.h"
#include "llvm/Type.h"
#include "llvm/ConstPoolVals.h"
#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)<