switch main LLI core execution to use an InstVisitor instead of a switch statement

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@6081 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2003-05-10 21:22:39 +00:00
parent 30ac0c0285
commit d7916e988c
2 changed files with 61 additions and 67 deletions

View File

@ -486,7 +486,8 @@ static GenericValue executeSetGTInst(GenericValue Src1, GenericValue Src2,
return Dest;
}
static void executeBinaryInst(BinaryOperator &I, ExecutionContext &SF) {
void Interpreter::visitBinaryOperator(BinaryOperator &I) {
ExecutionContext &SF = ECStack.back();
const Type *Ty = I.getOperand(0)->getType();
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
@ -577,7 +578,8 @@ void Interpreter::exitCalled(GenericValue GV) {
PerformExitStuff();
}
void Interpreter::executeRetInst(ReturnInst &I, ExecutionContext &SF) {
void Interpreter::visitReturnInst(ReturnInst &I) {
ExecutionContext &SF = ECStack.back();
const Type *RetTy = 0;
GenericValue Result;
@ -631,7 +633,8 @@ void Interpreter::executeRetInst(ReturnInst &I, ExecutionContext &SF) {
}
}
void Interpreter::executeBrInst(BranchInst &I, ExecutionContext &SF) {
void Interpreter::visitBranchInst(BranchInst &I) {
ExecutionContext &SF = ECStack.back();
BasicBlock *Dest;
Dest = I.getSuccessor(0); // Uncond branches have a fixed dest...
@ -643,7 +646,8 @@ void Interpreter::executeBrInst(BranchInst &I, ExecutionContext &SF) {
SwitchToNewBasicBlock(Dest, SF);
}
void Interpreter::executeSwitchInst(SwitchInst &I, ExecutionContext &SF) {
void Interpreter::visitSwitchInst(SwitchInst &I) {
ExecutionContext &SF = ECStack.back();
GenericValue CondVal = getOperandValue(I.getOperand(0), SF);
const Type *ElTy = I.getOperand(0)->getType();
@ -681,6 +685,8 @@ void Interpreter::SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF){
std::vector<GenericValue> ResultValues;
for (; PHINode *PN = dyn_cast<PHINode>(SF.CurInst); ++SF.CurInst) {
if (Trace) CW << "Run:" << PN;
// Search for the value corresponding to this previous bb...
int i = PN->getBasicBlockIndex(PrevBB);
assert(i != -1 && "PHINode doesn't contain entry for predecessor??");
@ -702,7 +708,9 @@ void Interpreter::SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF){
// Memory Instruction Implementations
//===----------------------------------------------------------------------===//
void Interpreter::executeAllocInst(AllocationInst &I, ExecutionContext &SF) {
void Interpreter::visitAllocationInst(AllocationInst &I) {
ExecutionContext &SF = ECStack.back();
const Type *Ty = I.getType()->getElementType(); // Type to be allocated
// Get the number of elements being allocated by the array...
@ -720,7 +728,8 @@ void Interpreter::executeAllocInst(AllocationInst &I, ExecutionContext &SF) {
ECStack.back().Allocas.add(Memory);
}
static void executeFreeInst(FreeInst &I, ExecutionContext &SF) {
void Interpreter::visitFreeInst(FreeInst &I) {
ExecutionContext &SF = ECStack.back();
assert(isa<PointerType>(I.getOperand(0)->getType()) && "Freeing nonptr?");
GenericValue Value = getOperandValue(I.getOperand(0), SF);
// TODO: Check to make sure memory is allocated
@ -784,19 +793,22 @@ GenericValue Interpreter::executeGEPOperation(Value *Ptr, User::op_iterator I,
return Result;
}
static void executeGEPInst(GetElementPtrInst &I, ExecutionContext &SF) {
void Interpreter::visitGetElementPtrInst(GetElementPtrInst &I) {
ExecutionContext &SF = ECStack.back();
SetValue(&I, TheEE->executeGEPOperation(I.getPointerOperand(),
I.idx_begin(), I.idx_end(), SF), SF);
}
void Interpreter::executeLoadInst(LoadInst &I, ExecutionContext &SF) {
void Interpreter::visitLoadInst(LoadInst &I) {
ExecutionContext &SF = ECStack.back();
GenericValue SRC = getOperandValue(I.getPointerOperand(), SF);
GenericValue *Ptr = (GenericValue*)GVTOP(SRC);
GenericValue Result = LoadValueFromMemory(Ptr, I.getType());
SetValue(&I, Result, SF);
}
void Interpreter::executeStoreInst(StoreInst &I, ExecutionContext &SF) {
void Interpreter::visitStoreInst(StoreInst &I) {
ExecutionContext &SF = ECStack.back();
GenericValue Val = getOperandValue(I.getOperand(0), SF);
GenericValue SRC = getOperandValue(I.getPointerOperand(), SF);
StoreValueToMemory(Val, (GenericValue *)GVTOP(SRC),
@ -809,8 +821,9 @@ void Interpreter::executeStoreInst(StoreInst &I, ExecutionContext &SF) {
// Miscellaneous Instruction Implementations
//===----------------------------------------------------------------------===//
void Interpreter::executeCallInst(CallInst &I, ExecutionContext &SF) {
ECStack.back().Caller = &I;
void Interpreter::visitCallInst(CallInst &I) {
ExecutionContext &SF = ECStack.back();
SF.Caller = &I;
std::vector<GenericValue> ArgVals;
ArgVals.reserve(I.getNumOperands()-1);
for (unsigned i = 1; i < I.getNumOperands(); ++i) {
@ -838,15 +851,15 @@ void Interpreter::executeCallInst(CallInst &I, ExecutionContext &SF) {
// To handle indirect calls, we must get the pointer value from the argument
// and treat it as a function pointer.
GenericValue SRC = getOperandValue(I.getCalledValue(), SF);
GenericValue SRC = getOperandValue(I.getCalledValue(), SF);
callFunction((Function*)GVTOP(SRC), ArgVals);
}
#define IMPLEMENT_SHIFT(OP, TY) \
case Type::TY##TyID: Dest.TY##Val = Src1.TY##Val OP Src2.UByteVal; break
static void executeShlInst(ShiftInst &I, ExecutionContext &SF) {
void Interpreter::visitShl(ShiftInst &I) {
ExecutionContext &SF = ECStack.back();
const Type *Ty = I.getOperand(0)->getType();
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
@ -867,7 +880,8 @@ static void executeShlInst(ShiftInst &I, ExecutionContext &SF) {
SetValue(&I, Dest, SF);
}
static void executeShrInst(ShiftInst &I, ExecutionContext &SF) {
void Interpreter::visitShr(ShiftInst &I) {
ExecutionContext &SF = ECStack.back();
const Type *Ty = I.getOperand(0)->getType();
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
@ -948,11 +962,14 @@ static GenericValue executeCastOperation(Value *SrcVal, const Type *Ty,
}
static void executeCastInst(CastInst &I, ExecutionContext &SF) {
void Interpreter::visitCastInst(CastInst &I) {
ExecutionContext &SF = ECStack.back();
SetValue(&I, executeCastOperation(I.getOperand(0), I.getType(), SF), SF);
}
static void executeVarArgInst(VarArgInst &I, ExecutionContext &SF) {
void Interpreter::visitVarArgInst(VarArgInst &I) {
ExecutionContext &SF = ECStack.back();
// Get the pointer to the valist element. LLI treats the valist in memory as
// an integer.
GenericValue VAListPtr = getOperandValue(I.getOperand(0), SF);
@ -1081,8 +1098,7 @@ bool Interpreter::executeInstruction() {
ExecutionContext &SF = ECStack.back(); // Current stack frame
Instruction &I = *SF.CurInst++; // Increment before execute
if (Trace)
CW << "Run:" << I;
if (Trace) CW << "Run:" << I;
// Track the number of dynamic instructions executed.
++NumDynamicInsts;
@ -1107,37 +1123,7 @@ bool Interpreter::executeInstruction() {
}
InInstruction = true;
if (I.isBinaryOp()) {
executeBinaryInst(cast<BinaryOperator>(I), SF);
} else {
switch (I.getOpcode()) {
// Terminators
case Instruction::Ret: executeRetInst (cast<ReturnInst>(I), SF); break;
case Instruction::Br: executeBrInst (cast<BranchInst>(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;
case Instruction::Free: executeFreeInst (cast<FreeInst> (I), SF); break;
case Instruction::Load: executeLoadInst (cast<LoadInst> (I), SF); break;
case Instruction::Store: executeStoreInst(cast<StoreInst>(I), SF); break;
case Instruction::GetElementPtr:
executeGEPInst(cast<GetElementPtrInst>(I), SF); break;
// Miscellaneous Instructions
case Instruction::Call: executeCallInst (cast<CallInst> (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::VarArg: executeVarArgInst(cast<VarArgInst>(I),SF); break;
default:
std::cout << "Don't know how to execute this instruction!\n-->" << I;
abort();
}
}
visit(I); // Dispatch to one of the visit* methods...
InInstruction = false;
// Reset the current frame location to the top of stack

View File

@ -11,22 +11,16 @@
//#define PROFILE_STRUCTURE_FIELDS 1
#include "../ExecutionEngine.h"
#include "../GenericValue.h"
#include "Support/DataTypes.h"
#include "llvm/Assembly/CachedWriter.h"
#include "llvm/Target/TargetData.h"
#include "llvm/BasicBlock.h"
#include "../GenericValue.h"
#include "llvm/Support/InstVisitor.h"
extern CachedWriter CW; // Object to accelerate printing of LLVM
struct FunctionInfo; // Defined in ExecutionAnnotations.h
class CallInst;
class ReturnInst;
class BranchInst;
class SwitchInst;
class LoadInst;
class StoreInst;
class AllocationInst;
// AllocaHolder - Object to track all of the blocks of memory allocated by
// alloca. When the function returns, this object is poped off the execution
@ -78,7 +72,7 @@ struct ExecutionContext {
// Interpreter - This class represents the entirety of the interpreter.
//
class Interpreter : public ExecutionEngine {
class Interpreter : public ExecutionEngine, public InstVisitor<Interpreter> {
int ExitCode; // The exit code to be returned by the lli util
bool Debug; // Debug mode enabled?
bool Profile; // Profiling enabled?
@ -134,11 +128,28 @@ public:
void finish(); // Do the 'finish' command
// Opcode Implementations
void executeCallInst(CallInst &I, ExecutionContext &SF);
void executeRetInst(ReturnInst &I, ExecutionContext &SF);
void executeBrInst(BranchInst &I, ExecutionContext &SF);
void executeSwitchInst(SwitchInst &I, ExecutionContext &SF);
void executeAllocInst(AllocationInst &I, ExecutionContext &SF);
void visitReturnInst(ReturnInst &I);
void visitBranchInst(BranchInst &I);
void visitSwitchInst(SwitchInst &I);
void visitBinaryOperator(BinaryOperator &I);
void visitAllocationInst(AllocationInst &I);
void visitFreeInst(FreeInst &I);
void visitLoadInst(LoadInst &I);
void visitStoreInst(StoreInst &I);
void visitGetElementPtrInst(GetElementPtrInst &I);
void visitPHINode(PHINode &PN) { assert(0 && "PHI nodes already handled!"); }
void visitCastInst(CastInst &I);
void visitCallInst(CallInst &I);
void visitShl(ShiftInst &I);
void visitShr(ShiftInst &I);
void visitVarArgInst(VarArgInst &I);
void visitInstruction(Instruction &I) {
std::cerr << I;
assert(0 && "Instruction not interpretable yet!");
}
GenericValue callExternalFunction(Function *F,
const std::vector<GenericValue> &ArgVals);
void exitCalled(GenericValue GV);
@ -157,9 +168,6 @@ public:
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
// SwitchToNewBasicBlock - Start execution in a new basic block and run any