From d7916e988c544b2ab6af26b723b6bc340ecb78cc Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 10 May 2003 21:22:39 +0000 Subject: [PATCH] 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 --- lib/ExecutionEngine/Interpreter/Execution.cpp | 86 ++++++++----------- lib/ExecutionEngine/Interpreter/Interpreter.h | 42 +++++---- 2 files changed, 61 insertions(+), 67 deletions(-) diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp index 26ef06bc982..f03514dba2b 100644 --- a/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -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 ResultValues; for (; PHINode *PN = dyn_cast(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(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 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(I), SF); - } else { - switch (I.getOpcode()) { - // Terminators - case Instruction::Ret: executeRetInst (cast(I), SF); break; - case Instruction::Br: executeBrInst (cast(I), SF); break; - case Instruction::Switch: executeSwitchInst(cast(I), SF);break; - // Invoke not handled! - - // Memory Instructions - case Instruction::Alloca: - case Instruction::Malloc: executeAllocInst((AllocationInst&)I, SF); break; - case Instruction::Free: executeFreeInst (cast (I), SF); break; - case Instruction::Load: executeLoadInst (cast (I), SF); break; - case Instruction::Store: executeStoreInst(cast(I), SF); break; - case Instruction::GetElementPtr: - executeGEPInst(cast(I), SF); break; - - // Miscellaneous Instructions - case Instruction::Call: executeCallInst (cast (I), SF); break; - case Instruction::PHINode: assert(0 && "PHI nodes already handled!"); - case Instruction::Cast: executeCastInst (cast (I), SF); break; - case Instruction::Shl: executeShlInst (cast(I), SF); break; - case Instruction::Shr: executeShrInst (cast(I), SF); break; - case Instruction::VarArg: executeVarArgInst(cast(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 diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.h b/lib/ExecutionEngine/Interpreter/Interpreter.h index 4d8c44ad760..6481cb7d42e 100644 --- a/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -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 { 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 &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 -- 2.40.0