X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FExecutionEngine%2FInterpreter%2FInterpreter.h;h=0dc0463903d4d4606c7ef6296d126ee66cae32ac;hb=c16fc548515f2fd01bc2cbe4befd822a636cc154;hp=26ed2dc6d156141cc89ff682433cc0b16db88c0d;hpb=fd13129bdf7324b2e8181a653897269aaaecc4e8;p=oota-llvm.git diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.h b/lib/ExecutionEngine/Interpreter/Interpreter.h index 26ed2dc6d15..0dc0463903d 100644 --- a/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -1,52 +1,60 @@ //===-- Interpreter.h ------------------------------------------*- C++ -*--===// // +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// // This header file defines the interpreter structure // //===----------------------------------------------------------------------===// -#ifndef LLI_INTERPRETER_H -#define LLI_INTERPRETER_H +#ifndef LLVM_LIB_EXECUTIONENGINE_INTERPRETER_INTERPRETER_H +#define LLVM_LIB_EXECUTIONENGINE_INTERPRETER_INTERPRETER_H -#include "llvm/BasicBlock.h" -#include "llvm/Assembly/CachedWriter.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/Support/InstVisitor.h" -#include "llvm/Target/TargetData.h" -#include "Support/DataTypes.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstVisitor.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +namespace llvm { -extern CachedWriter CW; // Object to accelerate printing of LLVM +class IntrinsicLowering; +struct FunctionInfo; +template class generic_gep_type_iterator; +class ConstantExpr; +typedef generic_gep_type_iterator gep_type_iterator; -struct FunctionInfo; // Defined in ExecutionAnnotations.h // AllocaHolder - Object to track all of the blocks of memory allocated by -// alloca. When the function returns, this object is poped off the execution +// alloca. When the function returns, this object is popped off the execution // stack, which causes the dtor to be run, which frees all the alloca'd memory. // class AllocaHolder { - friend class AllocaHolderHandle; - std::vector Allocations; - unsigned RefCnt; + std::vector Allocations; + public: - AllocaHolder() : RefCnt(0) {} - void add(void *mem) { Allocations.push_back(mem); } - ~AllocaHolder() { - for (unsigned i = 0; i < Allocations.size(); ++i) - free(Allocations[i]); + AllocaHolder() {} + + // Make this type move-only. Define explicit move special members for MSVC. + AllocaHolder(AllocaHolder &&RHS) : Allocations(std::move(RHS.Allocations)) {} + AllocaHolder &operator=(AllocaHolder &&RHS) { + Allocations = std::move(RHS.Allocations); + return *this; } -}; -// AllocaHolderHandle gives AllocaHolder value semantics so we can stick it into -// a vector... -// -class AllocaHolderHandle { - AllocaHolder *H; -public: - AllocaHolderHandle() : H(new AllocaHolder()) { H->RefCnt++; } - AllocaHolderHandle(const AllocaHolderHandle &AH) : H(AH.H) { H->RefCnt++; } - ~AllocaHolderHandle() { if (--H->RefCnt == 0) delete H; } + ~AllocaHolder() { + for (void *Allocation : Allocations) + free(Allocation); + } - void add(void *mem) { H->add(mem); } + void add(void *Mem) { Allocations.push_back(Mem); } }; typedef std::vector ValuePlaneTy; @@ -58,22 +66,37 @@ struct ExecutionContext { Function *CurFunction;// The currently executing function BasicBlock *CurBB; // The currently executing BB BasicBlock::iterator CurInst; // The next instruction to execute - FunctionInfo *FuncInfo; // The FuncInfo annotation for the function - std::vector Values;// ValuePlanes for each type + CallSite Caller; // Holds the call that called subframes. + // NULL if main func or debugger invoked fn + std::map Values; // LLVM values used in this invocation std::vector VarArgs; // Values passed through an ellipsis + AllocaHolder Allocas; // Track memory allocated by alloca - CallInst *Caller; // Holds the call that called subframes. - // NULL if main func or debugger invoked fn - AllocaHolderHandle Allocas; // Track memory allocated by alloca + ExecutionContext() : CurFunction(nullptr), CurBB(nullptr), CurInst(nullptr) {} + + ExecutionContext(ExecutionContext &&O) + : CurFunction(O.CurFunction), CurBB(O.CurBB), CurInst(O.CurInst), + Caller(O.Caller), Values(std::move(O.Values)), + VarArgs(std::move(O.VarArgs)), Allocas(std::move(O.Allocas)) {} + + ExecutionContext &operator=(ExecutionContext &&O) { + CurFunction = O.CurFunction; + CurBB = O.CurBB; + CurInst = O.CurInst; + Caller = O.Caller; + Values = std::move(O.Values); + VarArgs = std::move(O.VarArgs); + Allocas = std::move(O.Allocas); + return *this; + } }; // Interpreter - This class represents the entirety of the interpreter. // class Interpreter : public ExecutionEngine, public InstVisitor { - int ExitCode; // The exit code to be returned by the lli util - bool Trace; // Tracing enabled? - int CurFrame; // The current stack frame being inspected - TargetData TD; + GenericValue ExitValue; // The return value of the called function + DataLayout TD; + IntrinsicLowering *IL; // The runtime stack of executing code. The top of the stack is the current // function record. @@ -82,60 +105,95 @@ class Interpreter : public ExecutionEngine, public InstVisitor { // AtExitHandlers - List of functions to call when the program exits, // registered with the atexit() library function. std::vector AtExitHandlers; + public: - Interpreter(Module *M, bool isLittleEndian, bool isLongPointer, - bool TraceMode); - inline ~Interpreter() { CW.setModule(0); } + explicit Interpreter(std::unique_ptr M); + ~Interpreter() override; - /// runAtExitHandlers - Run any functions registered by the - /// program's calls to atexit(3), which we intercept and store in - /// AtExitHandlers. + /// runAtExitHandlers - Run any functions registered by the program's calls to + /// atexit(3), which we intercept and store in AtExitHandlers. /// - void runAtExitHandlers (); + void runAtExitHandlers(); + + static void Register() { + InterpCtor = create; + } - /// create - Create an interpreter ExecutionEngine. This can never fail. + /// Create an interpreter ExecutionEngine. /// - static ExecutionEngine *create(Module *M, bool TraceMode); + static ExecutionEngine *create(std::unique_ptr M, + std::string *ErrorStr = nullptr); /// run - Start execution with the specified function and arguments. /// - virtual GenericValue run(Function *F, - const std::vector &ArgValues); + GenericValue runFunction(Function *F, + const std::vector &ArgValues) override; - // Methods used for debug printouts: - static void print(const Type *Ty, GenericValue V); - static void printValue(const Type *Ty, GenericValue V); + void *getPointerToNamedFunction(StringRef Name, + bool AbortOnFailure = true) override { + // FIXME: not implemented. + return nullptr; + } // Methods used to execute code: // Place a call on the stack void callFunction(Function *F, const std::vector &ArgVals); - void executeInstruction(); // Execute one instruction void run(); // Execute instructions until nothing left to do // Opcode Implementations void visitReturnInst(ReturnInst &I); void visitBranchInst(BranchInst &I); void visitSwitchInst(SwitchInst &I); + void visitIndirectBrInst(IndirectBrInst &I); void visitBinaryOperator(BinaryOperator &I); - void visitAllocationInst(AllocationInst &I); - void visitFreeInst(FreeInst &I); + void visitICmpInst(ICmpInst &I); + void visitFCmpInst(FCmpInst &I); + void visitAllocaInst(AllocaInst &I); void visitLoadInst(LoadInst &I); void visitStoreInst(StoreInst &I); void visitGetElementPtrInst(GetElementPtrInst &I); + void visitPHINode(PHINode &PN) { + llvm_unreachable("PHI nodes already handled!"); + } + void visitTruncInst(TruncInst &I); + void visitZExtInst(ZExtInst &I); + void visitSExtInst(SExtInst &I); + void visitFPTruncInst(FPTruncInst &I); + void visitFPExtInst(FPExtInst &I); + void visitUIToFPInst(UIToFPInst &I); + void visitSIToFPInst(SIToFPInst &I); + void visitFPToUIInst(FPToUIInst &I); + void visitFPToSIInst(FPToSIInst &I); + void visitPtrToIntInst(PtrToIntInst &I); + void visitIntToPtrInst(IntToPtrInst &I); + void visitBitCastInst(BitCastInst &I); + void visitSelectInst(SelectInst &I); + + + void visitCallSite(CallSite CS); + void visitCallInst(CallInst &I) { visitCallSite (CallSite (&I)); } + void visitInvokeInst(InvokeInst &I) { visitCallSite (CallSite (&I)); } + void visitUnreachableInst(UnreachableInst &I); + + void visitShl(BinaryOperator &I); + void visitLShr(BinaryOperator &I); + void visitAShr(BinaryOperator &I); + + void visitVAArgInst(VAArgInst &I); + void visitExtractElementInst(ExtractElementInst &I); + void visitInsertElementInst(InsertElementInst &I); + void visitShuffleVectorInst(ShuffleVectorInst &I); + + void visitExtractValueInst(ExtractValueInst &I); + void visitInsertValueInst(InsertValueInst &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!"); + errs() << I << "\n"; + llvm_unreachable("Instruction not interpretable yet!"); } - GenericValue callExternalFunction(Function *F, + GenericValue callExternalFunction(Function *F, const std::vector &ArgVals); void exitCalled(GenericValue GV); @@ -143,25 +201,56 @@ public: AtExitHandlers.push_back(F); } - //FIXME: private: -public: - GenericValue executeGEPOperation(Value *Ptr, User::op_iterator I, - User::op_iterator E, ExecutionContext &SF); + GenericValue *getFirstVarArg () { + return &(ECStack.back ().VarArgs[0]); + } private: // Helper functions + GenericValue executeGEPOperation(Value *Ptr, gep_type_iterator I, + gep_type_iterator E, ExecutionContext &SF); + // SwitchToNewBasicBlock - Start execution in a new basic block and run any // PHI nodes in the top of the block. This is used for intraprocedural // control flow. - // + // void SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF); - void *getPointerToFunction(Function *F) { return (void*)F; } + void *getPointerToFunction(Function *F) override { return (void*)F; } - void initializeExecutionEngine(); + void initializeExecutionEngine() { } void initializeExternalFunctions(); + GenericValue getConstantExprValue(ConstantExpr *CE, ExecutionContext &SF); GenericValue getOperandValue(Value *V, ExecutionContext &SF); - GenericValue executeCastOperation(Value *SrcVal, const Type *Ty, - ExecutionContext &SF); + GenericValue executeTruncInst(Value *SrcVal, Type *DstTy, + ExecutionContext &SF); + GenericValue executeSExtInst(Value *SrcVal, Type *DstTy, + ExecutionContext &SF); + GenericValue executeZExtInst(Value *SrcVal, Type *DstTy, + ExecutionContext &SF); + GenericValue executeFPTruncInst(Value *SrcVal, Type *DstTy, + ExecutionContext &SF); + GenericValue executeFPExtInst(Value *SrcVal, Type *DstTy, + ExecutionContext &SF); + GenericValue executeFPToUIInst(Value *SrcVal, Type *DstTy, + ExecutionContext &SF); + GenericValue executeFPToSIInst(Value *SrcVal, Type *DstTy, + ExecutionContext &SF); + GenericValue executeUIToFPInst(Value *SrcVal, Type *DstTy, + ExecutionContext &SF); + GenericValue executeSIToFPInst(Value *SrcVal, Type *DstTy, + ExecutionContext &SF); + GenericValue executePtrToIntInst(Value *SrcVal, Type *DstTy, + ExecutionContext &SF); + GenericValue executeIntToPtrInst(Value *SrcVal, Type *DstTy, + ExecutionContext &SF); + GenericValue executeBitCastInst(Value *SrcVal, Type *DstTy, + ExecutionContext &SF); + GenericValue executeCastOperation(Instruction::CastOps opcode, Value *SrcVal, + Type *Ty, ExecutionContext &SF); + void popStackAndReturnValueToCaller(Type *RetTy, GenericValue Result); + }; +} // End llvm namespace + #endif