diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp index b8cb4909342..9ad5abab2d9 100644 --- a/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -419,6 +419,15 @@ static void executeBinaryInst(BinaryOperator *I, ExecutionContext &SF) { // Terminator Instruction Implementations //===----------------------------------------------------------------------===// +void Interpreter::exitCalled(GenericValue GV) { + cout << "Program returned "; + print(Type::IntTy, GV); + cout << " via 'void exit(int)'\n"; + + ExitCode = GV.SByteVal; + ECStack.clear(); +} + void Interpreter::executeRetInst(ReturnInst *I, ExecutionContext &SF) { const Type *RetTy = 0; GenericValue Result; diff --git a/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp index bcd584a6b5c..973cca68422 100644 --- a/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp +++ b/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp @@ -18,6 +18,24 @@ typedef GenericValue (*ExFunc)(MethodType *, const vector &); static map Functions; +static Interpreter *TheInterpreter; + +// getCurrentExecutablePath() - Return the directory that the lli executable +// lives in. +// +string Interpreter::getCurrentExecutablePath() const { + Dl_info Info; + if (dladdr(&TheInterpreter, &Info) == 0) return ""; + + string LinkAddr(Info.dli_fname); + unsigned SlashPos = LinkAddr.rfind('/'); + if (SlashPos != 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'; @@ -61,6 +79,8 @@ static ExFunc lookupMethod(const Method *M) { void Interpreter::callExternalMethod(Method *M, const vector &ArgVals) { + TheInterpreter = this; + // Do a lookup to see if the method is in our cache... this should just be a // defered annotation! map::iterator FI = Functions.find(M); @@ -127,10 +147,16 @@ GenericValue lle_Vb_putchar(MethodType *M, const vector &Args) { return GenericValue(); } +// int "putchar"(int) +GenericValue lle_ii_putchar(MethodType *M, const vector &Args) { + cout << ((char)Args[0].IntVal) << flush; + return Args[0]; +} + // void "putchar"(ubyte) GenericValue lle_VB_putchar(MethodType *M, const vector &Args) { - cout << Args[0].UByteVal; - return GenericValue(); + cout << Args[0].SByteVal << flush; + return Args[0]; } // void "__main"() @@ -138,4 +164,10 @@ GenericValue lle_V___main(MethodType *M, const vector &Args) { return GenericValue(); } +// void "exit"(int) +GenericValue lle_Vi_exit(MethodType *M, const vector &Args) { + TheInterpreter->exitCalled(Args[0]); + return GenericValue(); +} + } // End extern "C" diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.h b/lib/ExecutionEngine/Interpreter/Interpreter.h index 8c2f32566a5..d9a6834128d 100644 --- a/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -108,6 +108,7 @@ public: void executeRetInst(ReturnInst *I, ExecutionContext &SF); void executeBrInst(BranchInst *I, ExecutionContext &SF); void executeAllocInst(AllocationInst *I, ExecutionContext &SF); + void exitCalled(GenericValue GV); // getCurrentMethod - Return the currently executing method inline Method *getCurrentMethod() const { @@ -120,6 +121,11 @@ public: inline bool isStopped() const { return !ECStack.empty(); } private: // Helper functions + // getCurrentExecutablePath() - Return the directory that the lli executable + // lives in. + // + string getCurrentExecutablePath() const; + // printCurrentInstruction - Print out the instruction that the virtual PC is // at, or fail silently if no program is running. // diff --git a/lib/ExecutionEngine/Interpreter/UserInput.cpp b/lib/ExecutionEngine/Interpreter/UserInput.cpp index f579ef1a9b4..2989ae95e86 100644 --- a/lib/ExecutionEngine/Interpreter/UserInput.cpp +++ b/lib/ExecutionEngine/Interpreter/UserInput.cpp @@ -8,6 +8,7 @@ #include "llvm/Bytecode/Reader.h" #include "llvm/Assembly/Writer.h" #include "llvm/DerivedTypes.h" +#include "llvm/Transforms/Linker.h" #include enum CommandID { @@ -129,15 +130,25 @@ void Interpreter::handleUserInput() { // loadModule - Load a new module to execute... // void Interpreter::loadModule(const string &Filename) { + string ErrorMsg; if (CurMod && !flushModule()) return; // Kill current execution - CurMod = ParseBytecodeFile(Filename); + CurMod = ParseBytecodeFile(Filename, &ErrorMsg); if (CurMod == 0) { - cout << "Error parsing '" << Filename << "': No module loaded.\n"; + cout << "Error parsing '" << Filename << "': No module loaded: " + << ErrorMsg << "\n"; return; } - // TODO: link in support library... + string RuntimeLib = getCurrentExecutablePath() + "/RuntimeLib.bc"; + if (Module *SupportLib = ParseBytecodeFile(RuntimeLib, &ErrorMsg)) { + if (LinkModules(CurMod, SupportLib, &ErrorMsg)) + cerr << "Error Linking runtime library into current module: " + << ErrorMsg << endl; + } else { + cerr << "Error loading runtime library '"+RuntimeLib+"': " + << ErrorMsg << "\n"; + } } diff --git a/lib/ExecutionEngine/Makefile b/lib/ExecutionEngine/Makefile index b1b936d3bf0..3e70896c291 100644 --- a/lib/ExecutionEngine/Makefile +++ b/lib/ExecutionEngine/Makefile @@ -1,6 +1,7 @@ LEVEL = ../.. TOOLNAME = lli -USEDLIBS = opt bcreader bcwriter vmcore asmwriter analysis support target +USEDLIBS = opt bcreader bcwriter vmcore asmwriter analysis support \ + target transforms TOOLLINKOPTS = -ldl include $(LEVEL)/Makefile.common @@ -14,6 +15,6 @@ Debug/RuntimeLib.o: Debug/RuntimeLib.c /home/vadve/lattner/cvs/gcc_install/bin/gcc $< -c -o $@ $(LEVEL)/tools/Debug/RuntimeLib.bc: Debug/RuntimeLib.o - opt -dce $< -o $@ -f -q + ../Debug/opt -dce $< -o $@ -f -q diff --git a/tools/lli/Makefile b/tools/lli/Makefile index b1b936d3bf0..3e70896c291 100644 --- a/tools/lli/Makefile +++ b/tools/lli/Makefile @@ -1,6 +1,7 @@ LEVEL = ../.. TOOLNAME = lli -USEDLIBS = opt bcreader bcwriter vmcore asmwriter analysis support target +USEDLIBS = opt bcreader bcwriter vmcore asmwriter analysis support \ + target transforms TOOLLINKOPTS = -ldl include $(LEVEL)/Makefile.common @@ -14,6 +15,6 @@ Debug/RuntimeLib.o: Debug/RuntimeLib.c /home/vadve/lattner/cvs/gcc_install/bin/gcc $< -c -o $@ $(LEVEL)/tools/Debug/RuntimeLib.bc: Debug/RuntimeLib.o - opt -dce $< -o $@ -f -q + ../Debug/opt -dce $< -o $@ -f -q