mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-20 19:25:05 +00:00
Make CreateArgv part of lli rather than part of ExecutionEngine.
Switch Interpreter and JIT's "run" methods to take a Function and a vector of GenericValues. Move (almost all of) the stuff that constructs a canonical call to main() into lli (new methods "callAsMain", "makeStringVector"). Nuke getCurrentExecutablePath(), enableTracing(), getCurrentFunction(), isStopped(), and many dead decls from interpreter. Add linux strdup() support to interpreter. Make interpreter's atexit handler runner and JIT's runAtExitHandlers() look more alike, in preparation for refactoring. atexit() is spelled "atexit", not "at_exit". git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8366 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5bea411ad2
commit
70975eef57
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/// 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()");
|
||||
|
||||
// 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;
|
||||
// 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]);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
virtual GenericValue run(Function *F,
|
||||
const std::vector<GenericValue> &ArgValues);
|
||||
|
||||
void enableTracing() { Trace = true; }
|
||||
|
||||
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();
|
||||
};
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user