diff options
Diffstat (limited to 'lib/ExecutionEngine/Interpreter')
-rw-r--r-- | lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp | 22 | ||||
-rw-r--r-- | lib/ExecutionEngine/Interpreter/Interpreter.cpp | 89 | ||||
-rw-r--r-- | lib/ExecutionEngine/Interpreter/Interpreter.h | 53 |
3 files changed, 54 insertions, 110 deletions
diff --git a/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp index d24557abe0..1a28e46d8d 100644 --- a/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp +++ b/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp @@ -29,22 +29,6 @@ static std::map<std::string, ExFunc> FuncNames; static Interpreter *TheInterpreter; -// getCurrentExecutablePath() - Return the directory that the lli executable -// lives in. -// -std::string Interpreter::getCurrentExecutablePath() const { - Dl_info Info; - if (dladdr(&TheInterpreter, &Info) == 0) return ""; - - std::string LinkAddr(Info.dli_fname); - unsigned SlashPos = LinkAddr.rfind('/'); - if (SlashPos != std::string::npos) - LinkAddr.resize(SlashPos); // Trim the executable name off... - - return LinkAddr; -} - - static char getTypeID(const Type *Ty) { switch (Ty->getPrimitiveID()) { case Type::VoidTyID: return 'V'; @@ -498,6 +482,12 @@ GenericValue lle_X_strlen(FunctionType *M, const vector<GenericValue> &Args) { return Ret; } +// char *strdup(const char *src); +GenericValue lle_X_strdup(FunctionType *M, const vector<GenericValue> &Args) { + assert(Args.size() == 1); + return PTOGV(strdup((char*)GVTOP(Args[0]))); +} + // char *__strdup(const char *src); GenericValue lle_X___strdup(FunctionType *M, const vector<GenericValue> &Args) { assert(Args.size() == 1); diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.cpp b/lib/ExecutionEngine/Interpreter/Interpreter.cpp index 6b82dada33..518290a9f7 100644 --- a/lib/ExecutionEngine/Interpreter/Interpreter.cpp +++ b/lib/ExecutionEngine/Interpreter/Interpreter.cpp @@ -54,69 +54,46 @@ Interpreter::Interpreter(Module *M, bool isLittleEndian, bool isLongPointer, emitGlobals(); } -/// run - Start execution with the specified function and arguments. -/// -int Interpreter::run(const std::string &MainFunction, - const std::vector<std::string> &Args, - const char ** envp) { - // Start interpreter into the main function... - // - if (!callMainFunction(MainFunction, Args)) { - // If the call succeeded, run the code now... +void Interpreter::runAtExitHandlers () { + while (!AtExitHandlers.empty()) { + callFunction(AtExitHandlers.back(), std::vector<GenericValue>()); + AtExitHandlers.pop_back(); run(); } - - do { - // If the program has exited, run atexit handlers... - if (ECStack.empty() && !AtExitHandlers.empty()) { - callFunction(AtExitHandlers.back(), std::vector<GenericValue>()); - AtExitHandlers.pop_back(); - run(); - } - } while (!ECStack.empty()); - - return ExitCode; } - -// callMainFunction - Construct call to typical C main() function and -// call it using callFunction(). -// -bool Interpreter::callMainFunction(const std::string &Name, - const std::vector<std::string> &InputArgv) { - Function *M = getModule().getNamedFunction(Name); - if (M == 0) { - std::cerr << "Could not find function '" << Name << "' in module!\n"; - return 1; - } - const FunctionType *MT = M->getFunctionType(); - - std::vector<GenericValue> Args; - if (MT->getParamTypes().size() >= 2) { - PointerType *SPP = PointerType::get(PointerType::get(Type::SByteTy)); - if (MT->getParamTypes()[1] != SPP) { - CW << "Second argument of '" << Name << "' should have type: '" - << SPP << "'!\n"; - return true; - } - Args.push_back(PTOGV(CreateArgv(InputArgv))); - } - - if (MT->getParamTypes().size() >= 1) { - if (!MT->getParamTypes()[0]->isInteger()) { - std::cout << "First argument of '" << Name - << "' should be an integer!\n"; - return true; - } else { - GenericValue GV; GV.UIntVal = InputArgv.size(); - Args.insert(Args.begin(), GV); - } +/// run - Start execution with the specified function and arguments. +/// +GenericValue Interpreter::run(Function *F, + const std::vector<GenericValue> &ArgValues) { + assert (F && "Function *F was null at entry to run()"); + + // Try extra hard not to pass extra args to a function that isn't + // expecting them. C programmers frequently bend the rules and + // declare main() with fewer parameters than it actually gets + // passed, and the interpreter barfs if you pass a function more + // parameters than it is declared to take. This does not attempt to + // take into account gratuitous differences in declared types, + // though. + std::vector<GenericValue> ActualArgs; + const unsigned ArgCount = F->getFunctionType()->getParamTypes().size(); + for (unsigned i = 0; i < ArgCount; ++i) { + ActualArgs.push_back (ArgValues[i]); } - - callFunction(M, Args); // Start executing it... + + // Set up the function call. + callFunction(F, ActualArgs); // Reset the current frame location to the top of stack CurFrame = ECStack.size()-1; - return false; + // Start executing the function. + run(); + + // Run any atexit handlers now! + runAtExitHandlers(); + + GenericValue rv; + rv.IntVal = ExitCode; + return rv; } diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.h b/lib/ExecutionEngine/Interpreter/Interpreter.h index 5434fe0b81..ef0540c1fe 100644 --- a/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -79,41 +79,38 @@ class Interpreter : public ExecutionEngine, public InstVisitor<Interpreter> { // function record. std::vector<ExecutionContext> ECStack; - // AtExitHandlers - List of functions to call when the program exits. + // AtExitHandlers - List of functions to call when the program exits, + // registered with the atexit() library function. std::vector<Function*> AtExitHandlers; public: Interpreter(Module *M, bool isLittleEndian, bool isLongPointer, bool TraceMode); inline ~Interpreter() { CW.setModule(0); } + /// runAtExitHandlers - Run any functions registered by the + /// program's calls to atexit(3), which we intercept and store in + /// AtExitHandlers. + /// + void runAtExitHandlers (); + /// create - Create an interpreter ExecutionEngine. This can never fail. /// static ExecutionEngine *create(Module *M, bool TraceMode); /// run - Start execution with the specified function and arguments. /// - virtual int run(const std::string &FnName, - const std::vector<std::string> &Args, - const char ** envp); - - - void enableTracing() { Trace = true; } + virtual GenericValue run(Function *F, + const std::vector<GenericValue> &ArgValues); - void handleUserInput(); - - // User Interation Methods... - bool callFunction(const std::string &Name); // return true on failure + // Methods used for debug printouts: static void print(const Type *Ty, GenericValue V); static void printValue(const Type *Ty, GenericValue V); - bool callMainFunction(const std::string &MainName, - const std::vector<std::string> &InputFilename); - - // Code execution methods... + // Methods used to execute code: + // Place a call on the stack void callFunction(Function *F, const std::vector<GenericValue> &ArgVals); - void executeInstruction(); // Execute one instruction... - - void run(); // Do the 'run' command + void executeInstruction(); // Execute one instruction + void run(); // Execute instructions until nothing left to do // Opcode Implementations void visitReturnInst(ReturnInst &I); @@ -142,16 +139,6 @@ public: const std::vector<GenericValue> &ArgVals); void exitCalled(GenericValue GV); - // getCurrentFunction - Return the currently executing function - inline Function *getCurrentFunction() const { - return CurFrame < 0 ? 0 : ECStack[CurFrame].CurFunction; - } - - // isStopped - Return true if a program is stopped. Return false if no - // program is running. - // - inline bool isStopped() const { return !ECStack.empty(); } - void addAtExitHandler(Function *F) { AtExitHandlers.push_back(F); } @@ -170,16 +157,6 @@ private: // Helper functions void *getPointerToFunction(Function *F) { return (void*)F; } - // getCurrentExecutablePath() - Return the directory that the lli executable - // lives in. - // - std::string getCurrentExecutablePath() const; - - // printCurrentInstruction - Print out the instruction that the virtual PC is - // at, or fail silently if no program is running. - // - void printCurrentInstruction(); - void initializeExecutionEngine(); void initializeExternalFunctions(); }; |