#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"
-#include "llvm/iMemory.h"
+#include "llvm/Module.h"
+#include "llvm/Instructions.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Constants.h"
#include "llvm/Assembly/Writer.h"
void Interpreter::initializeExecutionEngine() {
TheEE = this;
- AnnotationManager::registerAnnotationFactory(MethodInfoAID,
- &MethodInfo::Create);
+ AnnotationManager::registerAnnotationFactory(FunctionInfoAID,
+ &FunctionInfo::Create);
initializeSignalHandlers();
}
}
// Save previously executing meth
- const Function *M = ECStack.back().CurMethod;
+ const Function *M = ECStack.back().CurFunction;
// Pop the current stack frame... this invalidates SF
ECStack.pop_back();
}
void Interpreter::executeBrInst(BranchInst &I, ExecutionContext &SF) {
- SF.PrevBB = SF.CurBB; // Update PrevBB so that PHI nodes work...
BasicBlock *Dest;
Dest = I.getSuccessor(0); // Uncond branches have a fixed dest...
if (!I.isUnconditional()) {
Value *Cond = I.getCondition();
- GenericValue CondVal = getOperandValue(Cond, SF);
- if (CondVal.BoolVal == 0) // If false cond...
+ if (getOperandValue(Cond, SF).BoolVal == 0) // If false cond...
Dest = I.getSuccessor(1);
}
- SF.CurBB = Dest; // Update CurBB to branch destination
- SF.CurInst = SF.CurBB->begin(); // Update new instruction ptr...
+ SwitchToNewBasicBlock(Dest, SF);
}
-static void executeSwitch(SwitchInst &I, ExecutionContext &SF) {
+void Interpreter::executeSwitchInst(SwitchInst &I, ExecutionContext &SF) {
GenericValue CondVal = getOperandValue(I.getOperand(0), SF);
const Type *ElTy = I.getOperand(0)->getType();
- SF.PrevBB = SF.CurBB; // Update PrevBB so that PHI nodes work...
- BasicBlock *Dest = 0;
// Check to see if any of the cases match...
- for (unsigned i = 2, e = I.getNumOperands(); i != e; i += 2) {
+ BasicBlock *Dest = 0;
+ for (unsigned i = 2, e = I.getNumOperands(); i != e; i += 2)
if (executeSetEQInst(CondVal,
getOperandValue(I.getOperand(i), SF), ElTy).BoolVal) {
Dest = cast<BasicBlock>(I.getOperand(i+1));
break;
}
- }
if (!Dest) Dest = I.getDefaultDest(); // No cases matched: use default
- SF.CurBB = Dest; // Update CurBB to branch destination
- SF.CurInst = SF.CurBB->begin(); // Update new instruction ptr...
+ SwitchToNewBasicBlock(Dest, SF);
+}
+
+// SwitchToNewBasicBlock - This method is used to jump to a new basic block.
+// This function handles the actual updating of block and instruction iterators
+// as well as execution of all of the PHI nodes in the destination block.
+//
+// This method does this because all of the PHI nodes must be executed
+// atomically, reading their inputs before any of the results are updated. Not
+// doing this can cause problems if the PHI nodes depend on other PHI nodes for
+// their inputs. If the input PHI node is updated before it is read, incorrect
+// results can happen. Thus we use a two phase approach.
+//
+void Interpreter::SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF){
+ BasicBlock *PrevBB = SF.CurBB; // Remember where we came from...
+ SF.CurBB = Dest; // Update CurBB to branch destination
+ SF.CurInst = SF.CurBB->begin(); // Update new instruction ptr...
+
+ if (!isa<PHINode>(SF.CurInst)) return; // Nothing fancy to do
+
+ // Loop over all of the PHI nodes in the current block, reading their inputs.
+ std::vector<GenericValue> ResultValues;
+
+ for (; PHINode *PN = dyn_cast<PHINode>(SF.CurInst); ++SF.CurInst) {
+ // Search for the value corresponding to this previous bb...
+ int i = PN->getBasicBlockIndex(PrevBB);
+ assert(i != -1 && "PHINode doesn't contain entry for predecessor??");
+ Value *IncomingValue = PN->getIncomingValue(i);
+
+ // Save the incoming value for this PHI node...
+ ResultValues.push_back(getOperandValue(IncomingValue, SF));
+ }
+
+ // Now loop over all of the PHI nodes setting their values...
+ SF.CurInst = SF.CurBB->begin();
+ for (unsigned i = 0; PHINode *PN = dyn_cast<PHINode>(SF.CurInst);
+ ++SF.CurInst, ++i)
+ SetValue(PN, ResultValues[i], SF);
}
void Interpreter::executeLoadInst(LoadInst &I, ExecutionContext &SF) {
GenericValue SRC = getOperandValue(I.getPointerOperand(), SF);
GenericValue *Ptr = (GenericValue*)GVTOP(SRC);
- GenericValue Result;
-
- if (TD.isLittleEndian()) {
- switch (I.getType()->getPrimitiveID()) {
- case Type::BoolTyID:
- case Type::UByteTyID:
- case Type::SByteTyID: Result.UByteVal = Ptr->Untyped[0]; break;
- case Type::UShortTyID:
- case Type::ShortTyID: Result.UShortVal = (unsigned)Ptr->Untyped[0] |
- ((unsigned)Ptr->Untyped[1] << 8);
- break;
- case Type::FloatTyID:
- case Type::UIntTyID:
- case Type::IntTyID: Result.UIntVal = (unsigned)Ptr->Untyped[0] |
- ((unsigned)Ptr->Untyped[1] << 8) |
- ((unsigned)Ptr->Untyped[2] << 16) |
- ((unsigned)Ptr->Untyped[3] << 24);
- break;
- case Type::DoubleTyID:
- case Type::ULongTyID:
- case Type::LongTyID:
- case Type::PointerTyID: Result.ULongVal = (uint64_t)Ptr->Untyped[0] |
- ((uint64_t)Ptr->Untyped[1] << 8) |
- ((uint64_t)Ptr->Untyped[2] << 16) |
- ((uint64_t)Ptr->Untyped[3] << 24) |
- ((uint64_t)Ptr->Untyped[4] << 32) |
- ((uint64_t)Ptr->Untyped[5] << 40) |
- ((uint64_t)Ptr->Untyped[6] << 48) |
- ((uint64_t)Ptr->Untyped[7] << 56);
- break;
- default:
- std::cout << "Cannot load value of type " << *I.getType() << "!\n";
- abort();
- }
- } else {
- switch (I.getType()->getPrimitiveID()) {
- case Type::BoolTyID:
- case Type::UByteTyID:
- case Type::SByteTyID: Result.UByteVal = Ptr->Untyped[0]; break;
- case Type::UShortTyID:
- case Type::ShortTyID: Result.UShortVal = (unsigned)Ptr->Untyped[1] |
- ((unsigned)Ptr->Untyped[0] << 8);
- break;
- case Type::FloatTyID:
- case Type::UIntTyID:
- case Type::IntTyID: Result.UIntVal = (unsigned)Ptr->Untyped[3] |
- ((unsigned)Ptr->Untyped[2] << 8) |
- ((unsigned)Ptr->Untyped[1] << 16) |
- ((unsigned)Ptr->Untyped[0] << 24);
- break;
- case Type::DoubleTyID:
- case Type::ULongTyID:
- case Type::LongTyID:
- case Type::PointerTyID: Result.ULongVal = (uint64_t)Ptr->Untyped[7] |
- ((uint64_t)Ptr->Untyped[6] << 8) |
- ((uint64_t)Ptr->Untyped[5] << 16) |
- ((uint64_t)Ptr->Untyped[4] << 24) |
- ((uint64_t)Ptr->Untyped[3] << 32) |
- ((uint64_t)Ptr->Untyped[2] << 40) |
- ((uint64_t)Ptr->Untyped[1] << 48) |
- ((uint64_t)Ptr->Untyped[0] << 56);
- break;
- default:
- std::cout << "Cannot load value of type " << *I.getType() << "!\n";
- abort();
- }
- }
-
+ GenericValue Result = LoadValueFromMemory(Ptr, I.getType());
SetValue(&I, Result, SF);
}
// and treat it as a function pointer.
GenericValue SRC = getOperandValue(I.getCalledValue(), SF);
- callMethod((Function*)GVTOP(SRC), ArgVals);
-}
-
-static void executePHINode(PHINode &I, ExecutionContext &SF) {
- BasicBlock *PrevBB = SF.PrevBB;
- Value *IncomingValue = 0;
-
- // Search for the value corresponding to this previous bb...
- for (unsigned i = I.getNumIncomingValues(); i > 0;) {
- if (I.getIncomingBlock(--i) == PrevBB) {
- IncomingValue = I.getIncomingValue(i);
- break;
- }
- }
- assert(IncomingValue && "No PHI node predecessor for current PrevBB!");
-
- // Found the value, set as the result...
- SetValue(&I, getOperandValue(IncomingValue, SF), SF);
+ callFunction((Function*)GVTOP(SRC), ArgVals);
}
#define IMPLEMENT_SHIFT(OP, TY) \
SetValue(&I, executeCastOperation(I.getOperand(0), I.getType(), SF), SF);
}
+static void executeVarArgInst(VarArgInst &I, ExecutionContext &SF) {
+ // Get the pointer to the valist element. LLI treats the valist in memory as
+ // an integer.
+ GenericValue VAListPtr = getOperandValue(I.getOperand(0), SF);
+
+ // Load the pointer
+ GenericValue VAList =
+ TheEE->LoadValueFromMemory((GenericValue *)GVTOP(VAListPtr), Type::UIntTy);
+
+ unsigned Argument = VAList.IntVal++;
+
+ // Update the valist to point to the next argument...
+ TheEE->StoreValueToMemory(VAList, (GenericValue *)GVTOP(VAListPtr),
+ Type::UIntTy);
+
+ // Set the value...
+ assert(Argument < SF.VarArgs.size() &&
+ "Accessing past the last vararg argument!");
+ SetValue(&I, SF.VarArgs[Argument], SF);
+}
//===----------------------------------------------------------------------===//
// Dispatch and Execution Code
//===----------------------------------------------------------------------===//
-MethodInfo::MethodInfo(Function *F) : Annotation(MethodInfoAID) {
+FunctionInfo::FunctionInfo(Function *F) : Annotation(FunctionInfoAID) {
// Assign slot numbers to the function arguments...
for (Function::const_aiterator AI = F->abegin(), E = F->aend(); AI != E; ++AI)
AI->addAnnotation(new SlotNumber(getValueSlot(AI)));
II->addAnnotation(new InstNumber(++InstNum, getValueSlot(II)));
}
-unsigned MethodInfo::getValueSlot(const Value *V) {
+unsigned FunctionInfo::getValueSlot(const Value *V) {
unsigned Plane = V->getType()->getUniqueID();
if (Plane >= NumPlaneElements.size())
NumPlaneElements.resize(Plane+1, 0);
//===----------------------------------------------------------------------===//
-// callMethod - Execute the specified function...
+// callFunction - Execute the specified function...
//
-void Interpreter::callMethod(Function *M,
- const std::vector<GenericValue> &ArgVals) {
+void Interpreter::callFunction(Function *F,
+ const std::vector<GenericValue> &ArgVals) {
assert((ECStack.empty() || ECStack.back().Caller == 0 ||
ECStack.back().Caller->getNumOperands()-1 == ArgVals.size()) &&
"Incorrect number of arguments passed into function call!");
- if (M->isExternal()) {
- GenericValue Result = callExternalMethod(M, ArgVals);
- const Type *RetTy = M->getReturnType();
+ if (F->isExternal()) {
+ GenericValue Result = callExternalFunction(F, ArgVals);
+ const Type *RetTy = F->getReturnType();
// Copy the result back into the result variable if we are not returning
// void.
SF.Caller = 0; // We returned from the call...
} else if (!QuietMode) {
// print it.
- CW << "Function " << M->getType() << " \"" << M->getName()
+ CW << "Function " << F->getType() << " \"" << F->getName()
<< "\" returned ";
print(RetTy, Result);
std::cout << "\n";
// the function. Also calculate the number of values for each type slot
// active.
//
- MethodInfo *MethInfo = (MethodInfo*)M->getOrCreateAnnotation(MethodInfoAID);
+ FunctionInfo *FuncInfo =
+ (FunctionInfo*)F->getOrCreateAnnotation(FunctionInfoAID);
ECStack.push_back(ExecutionContext()); // Make a new stack frame...
ExecutionContext &StackFrame = ECStack.back(); // Fill it in...
- StackFrame.CurMethod = M;
- StackFrame.CurBB = M->begin();
+ StackFrame.CurFunction = F;
+ StackFrame.CurBB = F->begin();
StackFrame.CurInst = StackFrame.CurBB->begin();
- StackFrame.MethInfo = MethInfo;
+ StackFrame.FuncInfo = FuncInfo;
// Initialize the values to nothing...
- StackFrame.Values.resize(MethInfo->NumPlaneElements.size());
- for (unsigned i = 0; i < MethInfo->NumPlaneElements.size(); ++i) {
- StackFrame.Values[i].resize(MethInfo->NumPlaneElements[i]);
+ StackFrame.Values.resize(FuncInfo->NumPlaneElements.size());
+ for (unsigned i = 0; i < FuncInfo->NumPlaneElements.size(); ++i) {
+ StackFrame.Values[i].resize(FuncInfo->NumPlaneElements[i]);
// Taint the initial values of stuff
memset(&StackFrame.Values[i][0], 42,
- MethInfo->NumPlaneElements[i]*sizeof(GenericValue));
+ FuncInfo->NumPlaneElements[i]*sizeof(GenericValue));
}
- StackFrame.PrevBB = 0; // No previous BB for PHI nodes...
-
// Run through the function arguments and initialize their values...
- assert(ArgVals.size() == M->asize() &&
+ assert((ArgVals.size() == F->asize() ||
+ (ArgVals.size() > F->asize() && F->getFunctionType()->isVarArg())) &&
"Invalid number of values passed to function invocation!");
+
+ // Handle non-varargs arguments...
unsigned i = 0;
- for (Function::aiterator AI = M->abegin(), E = M->aend(); AI != E; ++AI, ++i)
+ for (Function::aiterator AI = F->abegin(), E = F->aend(); AI != E; ++AI, ++i)
SetValue(AI, ArgVals[i], StackFrame);
+
+ // Handle varargs arguments...
+ StackFrame.VarArgs.assign(ArgVals.begin()+i, ArgVals.end());
}
// executeInstruction - Interpret a single instruction, increment the "PC", and
// Terminators
case Instruction::Ret: executeRetInst (cast<ReturnInst>(I), SF); break;
case Instruction::Br: executeBrInst (cast<BranchInst>(I), SF); break;
- case Instruction::Switch: executeSwitch (cast<SwitchInst>(I), SF); break;
+ case Instruction::Switch: executeSwitchInst(cast<SwitchInst>(I), SF);break;
+ // Invoke not handled!
+
// Memory Instructions
case Instruction::Alloca:
case Instruction::Malloc: executeAllocInst((AllocationInst&)I, SF); break;
// Miscellaneous Instructions
case Instruction::Call: executeCallInst (cast<CallInst> (I), SF); break;
- case Instruction::PHINode: executePHINode (cast<PHINode> (I), SF); break;
+ case Instruction::PHINode: assert(0 && "PHI nodes already handled!");
+ case Instruction::Cast: executeCastInst (cast<CastInst> (I), SF); break;
case Instruction::Shl: executeShlInst (cast<ShiftInst>(I), SF); break;
case Instruction::Shr: executeShrInst (cast<ShiftInst>(I), SF); break;
- case Instruction::Cast: executeCastInst (cast<CastInst> (I), SF); break;
+ case Instruction::VarArg: executeVarArgInst(cast<VarArgInst>(I),SF); break;
default:
std::cout << "Don't know how to execute this instruction!\n-->" << I;
abort();
//
void Interpreter::printStackFrame(int FrameNo) {
if (FrameNo == -1) FrameNo = CurFrame;
- Function *F = ECStack[FrameNo].CurMethod;
+ Function *F = ECStack[FrameNo].CurFunction;
const Type *RetTy = F->getReturnType();
CW << ((FrameNo == CurFrame) ? '>' : '-') << "#" << FrameNo << ". "