aboutsummaryrefslogtreecommitdiff
path: root/lib/ExecutionEngine/Interpreter
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ExecutionEngine/Interpreter')
-rw-r--r--lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp22
-rw-r--r--lib/ExecutionEngine/Interpreter/Interpreter.cpp89
-rw-r--r--lib/ExecutionEngine/Interpreter/Interpreter.h53
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();
};