aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/ExecutionEngine/ExecutionEngine.h6
-rw-r--r--lib/ExecutionEngine/ExecutionEngine.cpp39
-rw-r--r--lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp22
-rw-r--r--lib/ExecutionEngine/Interpreter/Interpreter.cpp89
-rw-r--r--lib/ExecutionEngine/Interpreter/Interpreter.h53
-rw-r--r--lib/ExecutionEngine/JIT/Intercept.cpp25
-rw-r--r--lib/ExecutionEngine/JIT/JIT.cpp43
-rw-r--r--lib/ExecutionEngine/JIT/JIT.h5
-rw-r--r--lib/ExecutionEngine/JIT/VM.h5
-rw-r--r--tools/lli/lli.cpp81
10 files changed, 169 insertions, 199 deletions
diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h
index 89a264333a..fdb219df66 100644
--- a/include/llvm/ExecutionEngine/ExecutionEngine.h
+++ b/include/llvm/ExecutionEngine/ExecutionEngine.h
@@ -44,9 +44,8 @@ public:
/// run - Start execution with the specified function, arguments, and
/// environment.
///
- virtual int run(const std::string &FnName,
- const std::vector<std::string> &Args,
- const char ** envp) = 0;
+ virtual GenericValue run(Function *F,
+ const std::vector<GenericValue> &ArgValues) = 0;
static ExecutionEngine *create (Module *M, bool ForceInterpreter,
bool TraceMode);
@@ -83,7 +82,6 @@ public: // FIXME: protected: // API shared among subclasses
GenericValue getConstantValue(const Constant *C);
void StoreValueToMemory(GenericValue Val, GenericValue *Ptr, const Type *Ty);
GenericValue LoadValueFromMemory(GenericValue *Ptr, const Type *Ty);
- void *CreateArgv(const std::vector<std::string> &InputArgv);
void InitializeMemory(const Constant *Init, void *Addr);
};
diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp
index a00c969908..b4baf9f8ff 100644
--- a/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -316,45 +316,6 @@ void ExecutionEngine::InitializeMemory(const Constant *Init, void *Addr) {
}
}
-void *ExecutionEngine::CreateArgv(const std::vector<std::string> &InputArgv) {
- if (getTargetData().getPointerSize() == 8) { // 64 bit target?
- PointerTy *Result = new PointerTy[InputArgv.size()+1];
- DEBUG(std::cerr << "ARGV = " << (void*)Result << "\n");
-
- for (unsigned i = 0; i < InputArgv.size(); ++i) {
- unsigned Size = InputArgv[i].size()+1;
- char *Dest = new char[Size];
- DEBUG(std::cerr << "ARGV[" << i << "] = " << (void*)Dest << "\n");
-
- copy(InputArgv[i].begin(), InputArgv[i].end(), Dest);
- Dest[Size-1] = 0;
-
- // Endian safe: Result[i] = (PointerTy)Dest;
- StoreValueToMemory(PTOGV(Dest), (GenericValue*)(Result+i), Type::LongTy);
- }
- Result[InputArgv.size()] = 0;
- return Result;
-
- } else { // 32 bit target?
- int *Result = new int[InputArgv.size()+1];
- DEBUG(std::cerr << "ARGV = " << (void*)Result << "\n");
-
- for (unsigned i = 0; i < InputArgv.size(); ++i) {
- unsigned Size = InputArgv[i].size()+1;
- char *Dest = new char[Size];
- DEBUG(std::cerr << "ARGV[" << i << "] = " << (void*)Dest << "\n");
-
- copy(InputArgv[i].begin(), InputArgv[i].end(), Dest);
- Dest[Size-1] = 0;
-
- // Endian safe: Result[i] = (PointerTy)Dest;
- StoreValueToMemory(PTOGV(Dest), (GenericValue*)(Result+i), Type::IntTy);
- }
- Result[InputArgv.size()] = 0; // null terminate it
- return Result;
- }
-}
-
/// EmitGlobals - Emit all of the global variables to memory, storing their
/// addresses into GlobalAddress. This must make sure to copy the contents of
/// their initializers into the memory.
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();
};
diff --git a/lib/ExecutionEngine/JIT/Intercept.cpp b/lib/ExecutionEngine/JIT/Intercept.cpp
index 10fd97015f..09cbe28740 100644
--- a/lib/ExecutionEngine/JIT/Intercept.cpp
+++ b/lib/ExecutionEngine/JIT/Intercept.cpp
@@ -12,33 +12,38 @@
#include "Config/dlfcn.h" // dlsym access
#include <iostream>
-// AtExitList - List of functions registered with the at_exit function
-static std::vector<void (*)()> AtExitList;
+// AtExitHandlers - List of functions to call when the program exits,
+// registered with the atexit() library function.
+static std::vector<void (*)()> AtExitHandlers;
+/// runAtExitHandlers - Run any functions registered by the program's
+/// calls to atexit(3), which we intercept and store in
+/// AtExitHandlers.
+///
void VM::runAtExitHandlers() {
- while (!AtExitList.empty()) {
- void (*Fn)() = AtExitList.back();
- AtExitList.pop_back();
+ while (!AtExitHandlers.empty()) {
+ void (*Fn)() = AtExitHandlers.back();
+ AtExitHandlers.pop_back();
Fn();
}
}
//===----------------------------------------------------------------------===//
-// Function stubs that are invoked instead of raw system calls
+// Function stubs that are invoked instead of certain library calls
//===----------------------------------------------------------------------===//
// NoopFn - Used if we have nothing else to call...
static void NoopFn() {}
-// jit_exit - Used to intercept the "exit" system call.
+// jit_exit - Used to intercept the "exit" library call.
static void jit_exit(int Status) {
- VM::runAtExitHandlers(); // Run at_exit handlers...
+ VM::runAtExitHandlers(); // Run atexit handlers...
exit(Status);
}
-// jit_atexit - Used to intercept the "at_exit" system call.
+// jit_atexit - Used to intercept the "atexit" library call.
static int jit_atexit(void (*Fn)(void)) {
- AtExitList.push_back(Fn); // Take note of at_exit handler...
+ AtExitHandlers.push_back(Fn); // Take note of atexit handler...
return 0; // Always successful
}
diff --git a/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp
index 9a2dc1aacb..4c4c2221e3 100644
--- a/lib/ExecutionEngine/JIT/JIT.cpp
+++ b/lib/ExecutionEngine/JIT/JIT.cpp
@@ -6,6 +6,7 @@
//===----------------------------------------------------------------------===//
#include "VM.h"
+#include "../GenericValue.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetMachineImpls.h"
#include "llvm/Module.h"
@@ -100,38 +101,24 @@ VM::VM(Module *M, TargetMachine *tm) : ExecutionEngine(M), TM(*tm) {
emitGlobals();
}
-/// VM::run - This method begins the execution of a program beginning at the
-/// specified function name. The function is called with the specified
-/// arguments and array of environment variables (a la main()).
+/// run - Start execution with the specified function and arguments.
///
-/// Inputs:
-/// FnName - The name of the function as a C++ string.
-/// Args - A vector of C++ strings containing the arguments.
-/// envp - An array of C strings containing the environment.
-///
-/// Return value:
-/// 1 - An error occurred.
-/// Otherwise, the return value from the specified function is returned.
-///
-int VM::run(const std::string &FnName, const std::vector<std::string> &Args,
- const char **envp) {
- Function *F = getModule().getNamedFunction(FnName);
- if (F == 0) {
- std::cerr << "Could not find function '" << FnName << "' in module!\n";
- return 1;
- }
+GenericValue VM::run(Function *F, const std::vector<GenericValue> &ArgValues)
+{
+ assert (F && "Function *F was null at entry to run()");
- int (*PF)(int, char**, const char**) =
- (int(*)(int, char**, const char**))getPointerToFunction(F);
- assert(PF != 0 && "Null pointer to function?");
+ int (*PF)(int, char **, const char **) =
+ (int(*)(int, char **, const char **))getPointerToFunction(F);
+ assert(PF != 0 && "Pointer to fn's code was null after getPointerToFunction");
- // Build an argv vector...
- char **Argv = (char**)CreateArgv(Args);
-
- // Call the main function...
- int Result = PF(Args.size(), Argv, envp);
+ // Call the function.
+ int ExitCode = PF(ArgValues[0].IntVal, (char **) GVTOP (ArgValues[1]),
+ (const char **) GVTOP (ArgValues[2]));
// Run any atexit handlers now!
runAtExitHandlers();
- return Result;
+
+ GenericValue rv;
+ rv.IntVal = ExitCode;
+ return rv;
}
diff --git a/lib/ExecutionEngine/JIT/JIT.h b/lib/ExecutionEngine/JIT/JIT.h
index 764afcf66f..9a7a645a4e 100644
--- a/lib/ExecutionEngine/JIT/JIT.h
+++ b/lib/ExecutionEngine/JIT/JIT.h
@@ -33,9 +33,8 @@ public:
/// 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);
+ virtual GenericValue run(Function *F,
+ const std::vector<GenericValue> &ArgValues);
/// getPointerToNamedFunction - This method returns the address of the
/// specified function by using the dlsym function call. As such it is only
diff --git a/lib/ExecutionEngine/JIT/VM.h b/lib/ExecutionEngine/JIT/VM.h
index 764afcf66f..9a7a645a4e 100644
--- a/lib/ExecutionEngine/JIT/VM.h
+++ b/lib/ExecutionEngine/JIT/VM.h
@@ -33,9 +33,8 @@ public:
/// 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);
+ virtual GenericValue run(Function *F,
+ const std::vector<GenericValue> &ArgValues);
/// getPointerToNamedFunction - This method returns the address of the
/// specified function by using the dlsym function call. As such it is only
diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp
index db3526824a..125f075856 100644
--- a/tools/lli/lli.cpp
+++ b/tools/lli/lli.cpp
@@ -10,10 +10,14 @@
//===----------------------------------------------------------------------===//
#include "ExecutionEngine.h"
+#include "GenericValue.h"
#include "Support/CommandLine.h"
+#include "Support/Debug.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Module.h"
#include "llvm/Target/TargetMachineImpls.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Target/TargetData.h"
namespace {
cl::opt<std::string>
@@ -33,10 +37,82 @@ namespace {
cl::init(false));
}
+static std::vector<std::string> makeStringVector (const char **envp) {
+ std::vector<std::string> rv;
+ for (unsigned i = 0; envp[i]; ++i)
+ rv.push_back (envp[i]);
+ return rv;
+}
+
+static void *CreateArgv(ExecutionEngine *EE,
+ const std::vector<std::string> &InputArgv) {
+ if (EE->getTargetData().getPointerSize() == 8) { // 64 bit target?
+ PointerTy *Result = new PointerTy[InputArgv.size()+1];
+ DEBUG(std::cerr << "ARGV = " << (void*)Result << "\n");
+
+ for (unsigned i = 0; i < InputArgv.size(); ++i) {
+ unsigned Size = InputArgv[i].size()+1;
+ char *Dest = new char[Size];
+ DEBUG(std::cerr << "ARGV[" << i << "] = " << (void*)Dest << "\n");
+
+ std::copy(InputArgv[i].begin(), InputArgv[i].end(), Dest);
+ Dest[Size-1] = 0;
+
+ // Endian safe: Result[i] = (PointerTy)Dest;
+ EE->StoreValueToMemory(PTOGV(Dest), (GenericValue*)(Result+i),
+ Type::LongTy);
+ }
+ Result[InputArgv.size()] = 0;
+ return Result;
+ } else { // 32 bit target?
+ int *Result = new int[InputArgv.size()+1];
+ DEBUG(std::cerr << "ARGV = " << (void*)Result << "\n");
+
+ for (unsigned i = 0; i < InputArgv.size(); ++i) {
+ unsigned Size = InputArgv[i].size()+1;
+ char *Dest = new char[Size];
+ DEBUG(std::cerr << "ARGV[" << i << "] = " << (void*)Dest << "\n");
+
+ std::copy(InputArgv[i].begin(), InputArgv[i].end(), Dest);
+ Dest[Size-1] = 0;
+
+ // Endian safe: Result[i] = (PointerTy)Dest;
+ EE->StoreValueToMemory(PTOGV(Dest), (GenericValue*)(Result+i),
+ Type::IntTy);
+ }
+ Result[InputArgv.size()] = 0; // null terminate it
+ return Result;
+ }
+}
+
+/// callAsMain - Call the function named FnName from M as if its
+/// signature were int main (int argc, char **argv, const char
+/// **envp), using the contents of Args to determine argc & argv, and
+/// the contents of EnvVars to determine envp. Returns the result
+/// from calling FnName, or -1 and prints an error msg. if the named
+/// function cannot be found.
+///
+int callAsMain (ExecutionEngine *EE, Module *M, const std::string &FnName,
+ const std::vector<std::string> &Args,
+ const std::vector<std::string> &EnvVars) {
+ Function *Fn = M->getNamedFunction (FnName);
+ if (!Fn) {
+ std::cerr << "Function '" << FnName << "' not found in module.\n";
+ return -1;
+ }
+ std::vector<GenericValue> GVArgs;
+ GenericValue GVArgc;
+ GVArgc.IntVal = Args.size ();
+ GVArgs.push_back (GVArgc); // Arg #0 = argc.
+ GVArgs.push_back (PTOGV (CreateArgv (EE, Args))); // Arg #1 = argv.
+ GVArgs.push_back (PTOGV (CreateArgv (EE, EnvVars))); // Arg #2 = envp.
+ return EE->run (Fn, GVArgs).IntVal;
+}
+
//===----------------------------------------------------------------------===//
// main Driver function
//
-int main(int argc, char** argv, const char ** envp) {
+int main(int argc, char **argv, const char **envp) {
cl::ParseCommandLineOptions(argc, argv,
" llvm interpreter & dynamic compiler\n");
@@ -64,7 +140,8 @@ int main(int argc, char** argv, const char ** envp) {
InputArgv.insert(InputArgv.begin(), InputFile);
// Run the main function!
- int ExitCode = EE->run(MainFunction, InputArgv, envp);
+ int ExitCode = callAsMain (EE, M, MainFunction, InputArgv,
+ makeStringVector (envp));
// Now that we are done executing the program, shut down the execution engine
delete EE;