From f58815e161c8c91075dd1af7a277314190ebc286 Mon Sep 17 00:00:00 2001 From: Brian Gaeke Date: Thu, 4 Sep 2003 22:21:24 +0000 Subject: [PATCH] Interpreter cleanups: Get rid of support for DebugMode (make it always off). Mung some comments. Get rid of interpreter's PROFILE_STRUCTURE_FIELDS and PerformExitStuff which have been disabled forever. Get rid of -abort-on-exception (make it always on). Get rid of user interaction stuff (debug mode innards). Simplify Interpreter's callMainFunction(). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8344 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../llvm/ExecutionEngine/ExecutionEngine.h | 5 +- lib/ExecutionEngine/ExecutionEngine.cpp | 6 +- lib/ExecutionEngine/Interpreter/Execution.cpp | 81 +----- .../Interpreter/Interpreter.cpp | 18 +- lib/ExecutionEngine/Interpreter/Interpreter.h | 12 +- lib/ExecutionEngine/Interpreter/UserInput.cpp | 236 ++---------------- tools/lli/lli.cpp | 6 +- 7 files changed, 37 insertions(+), 327 deletions(-) diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index a0e54c14508..7dc2c0a42ce 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -49,7 +49,7 @@ public: const char ** envp) = 0; static ExecutionEngine *create (Module *M, bool ForceInterpreter, - bool DebugMode, bool TraceMode); + bool TraceMode); /// createJIT - Create an return a new JIT compiler if there is one available /// for the current target. Otherwise it returns null. @@ -58,8 +58,7 @@ public: /// createInterpreter - Create a new interpreter object. This can never fail. /// - static ExecutionEngine *createInterpreter(Module *M, bool DebugMode, - bool TraceMode); + static ExecutionEngine *createInterpreter(Module *M, bool TraceMode); void addGlobalMapping(const Function *F, void *Addr) { void *&CurVal = GlobalAddress[(const GlobalValue*)F]; diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 5691a248a06..dbcaf63cdee 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -21,16 +21,16 @@ Statistic<> NumInitBytes("lli", "Number of bytes of global vars initialized"); ExecutionEngine *ExecutionEngine::create (Module *M, bool ForceInterpreter, - bool DebugMode, bool TraceMode) { + bool TraceMode) { ExecutionEngine *EE = 0; // If there is nothing that is forcing us to use the interpreter, make a JIT. - if (!ForceInterpreter && !DebugMode && !TraceMode) + if (!ForceInterpreter && !TraceMode) EE = VM::create(M); // If we can't make a JIT, make an interpreter instead. if (EE == 0) - EE = Interpreter::create(M, DebugMode, TraceMode); + EE = Interpreter::create(M, TraceMode); return EE; } diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp index 84486c21eec..79c404aae06 100644 --- a/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -31,10 +31,6 @@ namespace { cl::opt ArrayChecksEnabled("array-checks", cl::desc("Enable array bound checks")); - - cl::opt - AbortOnExceptions("abort-on-exception", - cl::desc("Halt execution on a machine exception")); } // Create a TargetData structure to handle memory addressing and size/alignment @@ -42,14 +38,6 @@ namespace { // CachedWriter CW; // Object to accelerate printing of LLVM -#ifdef PROFILE_STRUCTURE_FIELDS -static cl::opt -ProfileStructureFields("profilestructfields", - cl::desc("Profile Structure Field Accesses")); -#include -static std::map > FieldAccessCounts; -#endif - sigjmp_buf SignalRecoverBuffer; static bool InInstruction = false; @@ -520,54 +508,6 @@ void Interpreter::visitBinaryOperator(BinaryOperator &I) { // Terminator Instruction Implementations //===----------------------------------------------------------------------===// -// PerformExitStuff - Print out counters and profiling information if -// applicable... -void Interpreter::PerformExitStuff() { -#ifdef PROFILE_STRUCTURE_FIELDS - // Print out structure field accounting information... - if (!FieldAccessCounts.empty()) { - CW << "Profile Field Access Counts:\n"; - std::map >::iterator - I = FieldAccessCounts.begin(), E = FieldAccessCounts.end(); - for (; I != E; ++I) { - std::vector &OfC = I->second; - CW << " '" << (Value*)I->first << "'\t- Sum="; - - unsigned Sum = 0; - for (unsigned i = 0; i < OfC.size(); ++i) - Sum += OfC[i]; - CW << Sum << " - "; - - for (unsigned i = 0; i < OfC.size(); ++i) { - if (i) CW << ", "; - CW << OfC[i]; - } - CW << "\n"; - } - CW << "\n"; - - CW << "Profile Field Access Percentages:\n"; - std::cout.precision(3); - for (I = FieldAccessCounts.begin(); I != E; ++I) { - std::vector &OfC = I->second; - unsigned Sum = 0; - for (unsigned i = 0; i < OfC.size(); ++i) - Sum += OfC[i]; - - CW << " '" << (Value*)I->first << "'\t- "; - for (unsigned i = 0; i < OfC.size(); ++i) { - if (i) CW << ", "; - CW << double(OfC[i])/Sum; - } - CW << "\n"; - } - CW << "\n"; - - FieldAccessCounts.clear(); - } -#endif -} - void Interpreter::exitCalled(GenericValue GV) { if (!QuietMode) { std::cout << "Program returned "; @@ -756,15 +696,6 @@ GenericValue Interpreter::executeGEPOperation(Value *Ptr, User::op_iterator I, assert(CPU->getType() == Type::UByteTy); unsigned Index = CPU->getValue(); -#ifdef PROFILE_STRUCTURE_FIELDS - if (ProfileStructureFields) { - // Do accounting for this field... - std::vector &OfC = FieldAccessCounts[STy]; - if (OfC.size() == 0) OfC.resize(STy->getElementTypes().size()); - OfC[Index]++; - } -#endif - Total += SLO->MemberOffsets[Index]; Ty = STy->getElementTypes()[Index]; } else if (const SequentialType *ST = cast(Ty)) { @@ -1107,16 +1038,8 @@ bool Interpreter::executeInstruction() { // if (int SigNo = sigsetjmp(SignalRecoverBuffer, 1)) { --SF.CurInst; // Back up to erroring instruction - if (SigNo != SIGINT) { - std::cout << "EXCEPTION OCCURRED [" << strsignal(SigNo) << "]:\n"; - printStackTrace(); - // If -abort-on-exception was specified, terminate LLI instead of trying - // to debug it. - // - if (AbortOnExceptions) exit(1); - } else if (SigNo == SIGINT) { - std::cout << "CTRL-C Detected, execution halted.\n"; - } + std::cout << "EXCEPTION OCCURRED [" << strsignal(SigNo) << "]\n"; + exit(1); InInstruction = false; return true; } diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.cpp b/lib/ExecutionEngine/Interpreter/Interpreter.cpp index 6f540e2d1a8..4f8c407340a 100644 --- a/lib/ExecutionEngine/Interpreter/Interpreter.cpp +++ b/lib/ExecutionEngine/Interpreter/Interpreter.cpp @@ -11,7 +11,7 @@ /// create - Create a new interpreter object. This can never fail. /// -ExecutionEngine *Interpreter::create(Module *M, bool DebugMode, bool TraceMode){ +ExecutionEngine *Interpreter::create(Module *M, bool TraceMode){ bool isLittleEndian; switch (M->getEndianness()) { case Module::LittleEndian: isLittleEndian = true; break; @@ -32,15 +32,15 @@ ExecutionEngine *Interpreter::create(Module *M, bool DebugMode, bool TraceMode){ break; } - return new Interpreter(M, isLittleEndian, isLongPointer, DebugMode,TraceMode); + return new Interpreter(M, isLittleEndian, isLongPointer, TraceMode); } //===----------------------------------------------------------------------===// // Interpreter ctor - Initialize stuff // Interpreter::Interpreter(Module *M, bool isLittleEndian, bool isLongPointer, - bool DebugMode, bool TraceMode) - : ExecutionEngine(M), ExitCode(0), Debug(DebugMode), Trace(TraceMode), + bool TraceMode) + : ExecutionEngine(M), ExitCode(0), Trace(TraceMode), CurFrame(-1), TD("lli", isLittleEndian, isLongPointer ? 8 : 4, isLongPointer ? 8 : 4, isLongPointer ? 8 : 4) { @@ -59,17 +59,12 @@ int Interpreter::run(const std::string &MainFunction, const char ** envp) { // Start interpreter into the main function... // - if (!callMainFunction(MainFunction, Args) && !Debug) { - // If not in debug mode and if the call succeeded, run the code now... + if (!callMainFunction(MainFunction, Args)) { + // If the call succeeded, run the code now... run(); } do { - // If debug mode, allow the user to interact... also, if the user pressed - // ctrl-c or execution hit an error, enter the event loop... - if (Debug || isStopped()) - handleUserInput(); - // If the program has exited, run atexit handlers... if (ECStack.empty() && !AtExitHandlers.empty()) { callFunction(AtExitHandlers.back(), std::vector()); @@ -78,7 +73,6 @@ int Interpreter::run(const std::string &MainFunction, } } while (!ECStack.empty()); - PerformExitStuff(); return ExitCode; } diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.h b/lib/ExecutionEngine/Interpreter/Interpreter.h index 459904da6db..47f5c95f152 100644 --- a/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -7,9 +7,6 @@ #ifndef LLI_INTERPRETER_H #define LLI_INTERPRETER_H -// Uncomment this line to enable profiling of structure field accesses. -//#define PROFILE_STRUCTURE_FIELDS 1 - #include "../ExecutionEngine.h" #include "../GenericValue.h" #include "Support/DataTypes.h" @@ -74,7 +71,6 @@ struct ExecutionContext { // 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? bool Trace; // Tracing enabled? int CurFrame; // The current stack frame being inspected @@ -88,12 +84,12 @@ class Interpreter : public ExecutionEngine, public InstVisitor { std::vector AtExitHandlers; public: Interpreter(Module *M, bool isLittleEndian, bool isLongPointer, - bool DebugMode, bool TraceMode); + bool TraceMode); inline ~Interpreter() { CW.setModule(0); } /// create - Create an interpreter ExecutionEngine. This can never fail. /// - static ExecutionEngine *create(Module *M, bool DebugMode, bool TraceMode); + static ExecutionEngine *create(Module *M, bool TraceMode); /// getExitCode - return the code that should be the exit code for the lli /// utility. @@ -220,10 +216,6 @@ private: // Helper functions Value *ChooseOneOption(const std::string &Name, const std::vector &Opts); - // PerformExitStuff - Print out counters and profiling information if - // applicable... - void PerformExitStuff(); - void initializeExecutionEngine(); void initializeExternalFunctions(); }; diff --git a/lib/ExecutionEngine/Interpreter/UserInput.cpp b/lib/ExecutionEngine/Interpreter/UserInput.cpp index 3f4493d19be..135c990c652 100644 --- a/lib/ExecutionEngine/Interpreter/UserInput.cpp +++ b/lib/ExecutionEngine/Interpreter/UserInput.cpp @@ -5,220 +5,41 @@ //===----------------------------------------------------------------------===// #include "Interpreter.h" -#include "llvm/Bytecode/Reader.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" -#include "llvm/Transforms/Utils/Linker.h" -#include - -enum CommandID { - Quit, Help, // Basics - Print, Info, List, StackTrace, Up, Down, // Inspection - Next, Step, Run, Finish, Call, // Control flow changes - Break, Watch, // Debugging - Flush, - TraceOpt, // Toggle features -}; - -// CommandTable - Build a lookup table for the commands available to the user... -static struct CommandTableElement { - const char *Name; - enum CommandID CID; - - inline bool operator<(const CommandTableElement &E) const { - return std::string(Name) < std::string(E.Name); - } - inline bool operator==(const std::string &S) const { - return std::string(Name) == S; - } -} CommandTable[] = { - { "quit" , Quit }, { "q", Quit }, { "", Quit }, // Empty str = eof - { "help" , Help }, { "h", Help }, - - { "print" , Print }, { "p", Print }, - { "list" , List }, - { "info" , Info }, - { "backtrace", StackTrace }, { "bt", StackTrace }, { "where", StackTrace }, - { "up" , Up }, - { "down" , Down }, - - { "next" , Next }, { "n", Next }, - { "step" , Step }, { "s", Step }, - { "run" , Run }, - { "finish" , Finish }, - { "call" , Call }, - - { "break" , Break }, { "b", Break }, - { "watch" , Watch }, - - { "flush" , Flush }, - - { "trace" , TraceOpt }, -}; -static CommandTableElement *CommandTableEnd = - CommandTable+sizeof(CommandTable)/sizeof(CommandTable[0]); - - -//===----------------------------------------------------------------------===// -// handleUserInput - Enter the input loop for the interpreter. This function -// returns when the user quits the interpreter. -// -void Interpreter::handleUserInput() { - bool UserQuit = false; - - // Sort the table... - std::sort(CommandTable, CommandTableEnd); - - // Print the instruction that we are stopped at... - printCurrentInstruction(); - - do { - std::string Command; - std::cout << "lli> " << std::flush; - std::cin >> Command; - - CommandTableElement *E = find(CommandTable, CommandTableEnd, Command); - - if (E == CommandTableEnd) { - std::cout << "Error: '" << Command << "' not recognized!\n"; - continue; - } - - switch (E->CID) { - case Quit: UserQuit = true; break; - case Print: - std::cin >> Command; - print(Command); - break; - case Info: - std::cin >> Command; - infoValue(Command); - break; - - case List: list(); break; - case StackTrace: printStackTrace(); break; - case Up: - if (CurFrame > 0) { --CurFrame; printStackFrame(); } - else std::cout << "Error: Already at root of stack!\n"; - break; - case Down: - if ((unsigned)CurFrame < ECStack.size()-1) { - ++CurFrame; - printStackFrame(); - } else - std::cout << "Error: Already at bottom of stack!\n"; - break; - case Next: nextInstruction(); break; - case Step: stepInstruction(); break; - case Run: run(); break; - case Finish: finish(); break; - case Call: - std::cin >> Command; - callFunction(Command); // Enter the specified function - finish(); // Run until it's complete - break; - - case TraceOpt: - Trace = !Trace; - std::cout << "Tracing " << (Trace ? "enabled\n" : "disabled\n"); - break; - - default: - std::cout << "Command '" << Command << "' unimplemented!\n"; - break; - } - - } while (!UserQuit); - AtExitHandlers.clear(); -} - -//===----------------------------------------------------------------------===// -// setBreakpoint - Enable a breakpoint at the specified location -// -void Interpreter::setBreakpoint(const std::string &Name) { - Value *PickedVal = ChooseOneOption(Name, LookupMatchingNames(Name)); - // TODO: Set a breakpoint on PickedVal -} - -//===----------------------------------------------------------------------===// -// callFunction - Enter the specified function... -// -bool Interpreter::callFunction(const std::string &Name) { - std::vector Options = LookupMatchingNames(Name); - - for (unsigned i = 0; i < Options.size(); ++i) { // Remove non-fn matches... - if (!isa(Options[i])) { - Options.erase(Options.begin()+i); - --i; - } - } - - Value *PickedMeth = ChooseOneOption(Name, Options); - if (PickedMeth == 0) - return true; - - Function *F = cast(PickedMeth); - - std::vector Args; - // TODO, get args from user... - - callFunction(F, Args); // Start executing it... - - // Reset the current frame location to the top of stack - CurFrame = ECStack.size()-1; - - return false; -} +#include "llvm/Module.h" // callMainFunction - This is a nasty gross hack that will dissapear when // callFunction can parse command line options and stuff for us. // bool Interpreter::callMainFunction(const std::string &Name, const std::vector &InputArgv) { - std::vector Options = LookupMatchingNames(Name); - - for (unsigned i = 0; i < Options.size(); ++i) { // Remove non-fn matches... - if (!isa(Options[i])) { - Options.erase(Options.begin()+i); - --i; - } + Function *M = getModule().getNamedFunction(Name); + if (M == 0) { + std::cerr << "Could not find function '" << Name << "' in module!\n"; + return 1; } - - Value *PickedMeth = ChooseOneOption(Name, Options); - if (PickedMeth == 0) - return true; - - Function *M = cast(PickedMeth); const FunctionType *MT = M->getFunctionType(); std::vector Args; - switch (MT->getParamTypes().size()) { - default: - std::cout << "Unknown number of arguments to synthesize for '" << Name - << "'!\n"; + 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; - case 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))); + } - 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); } - // fallthrough - case 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); - } - // fallthrough - case 0: - break; } callFunction(M, Args); // Start executing it... @@ -228,20 +49,3 @@ bool Interpreter::callMainFunction(const std::string &Name, return false; } - - - -void Interpreter::list() { - if (ECStack.empty()) - std::cout << "Error: No program executing!\n"; - else - CW << ECStack[CurFrame].CurFunction; // Just print the function out... -} - -void Interpreter::printStackTrace() { - if (ECStack.empty()) std::cout << "No program executing!\n"; - - for (unsigned i = 0; i < ECStack.size(); ++i) { - printStackFrame((int)i); - } -} diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp index 36af42168ad..d0d1c4997b4 100644 --- a/tools/lli/lli.cpp +++ b/tools/lli/lli.cpp @@ -26,8 +26,6 @@ namespace { MainFunction ("f", cl::desc("Function to execute"), cl::init("main"), cl::value_desc("function name")); - cl::opt DebugMode("d", cl::desc("Start program in debugger")); - cl::opt TraceMode("trace", cl::desc("Enable Tracing")); cl::opt ForceInterpreter("force-interpreter", @@ -60,10 +58,10 @@ int main(int argc, char** argv, const char ** envp) { } ExecutionEngine *EE = - ExecutionEngine::create (M, ForceInterpreter, DebugMode, TraceMode); + ExecutionEngine::create (M, ForceInterpreter, TraceMode); assert (EE && "Couldn't create an ExecutionEngine, not even an interpreter?"); - // Add the module name to the start of the argv vector... + // Add the module's name to the start of the vector of arguments to main(). // But delete .bc first, since programs (and users) might not expect to // see it. const std::string ByteCodeFileSuffix (".bc"); -- 2.34.1