aboutsummaryrefslogtreecommitdiff
path: root/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2001-09-10 04:50:17 +0000
committerChris Lattner <sabre@nondot.org>2001-09-10 04:50:17 +0000
commit7720c8e1a7a252e983e3f3e7f841d7901dfea80c (patch)
tree7842e661fe1896dee47c77d82023a746f3b83c62 /lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
parent365a76e46e7b22ee2cd7881d0a7055fc20930fd5 (diff)
Add support for external methods
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@529 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp')
-rw-r--r--lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp107
1 files changed, 107 insertions, 0 deletions
diff --git a/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
new file mode 100644
index 0000000000..11b2038a0d
--- /dev/null
+++ b/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
@@ -0,0 +1,107 @@
+//===-- ExternalMethods.cpp - Implement External Methods ------------------===//
+//
+// This file contains both code to deal with invoking "external" methods, but
+// also contains code that implements "exported" external methods.
+//
+// External methods in LLI are implemented by dlopen'ing the lli executable and
+// using dlsym to look op the methods that we want to invoke. If a method is
+// found, then the arguments are mangled and passed in to the function call.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Interpreter.h"
+#include "llvm/DerivedTypes.h"
+#include <map>
+#include <dlfcn.h>
+#include <link.h>
+
+typedef GenericValue (*ExFunc)(MethodType *, const vector<GenericValue> &);
+static map<const Method *, ExFunc> Functions;
+
+static char getTypeID(const Type *Ty) {
+ switch (Ty->getPrimitiveID()) {
+ case Type::VoidTyID: return 'V';
+ case Type::BoolTyID: return 'o';
+ case Type::UByteTyID: return 'B';
+ case Type::SByteTyID: return 'b';
+ case Type::UShortTyID: return 'S';
+ case Type::ShortTyID: return 's';
+ case Type::UIntTyID: return 'I';
+ case Type::IntTyID: return 'i';
+ case Type::ULongTyID: return 'L';
+ case Type::LongTyID: return 'l';
+ case Type::FloatTyID: return 'F';
+ case Type::DoubleTyID: return 'D';
+ case Type::PointerTyID: return 'P';
+ case Type::MethodTyID: return 'M';
+ case Type::StructTyID: return 'T';
+ case Type::ArrayTyID: return 'A';
+ case Type::OpaqueTyID: return 'O';
+ default: return 'U';
+ }
+}
+
+static ExFunc lookupMethod(const Method *M) {
+ // Function not found, look it up... start by figuring out what the
+ // composite function name should be.
+ string ExtName = "lle_";
+ const MethodType *MT = M->getType()->isMethodType();
+ for (unsigned i = 0; const Type *Ty = MT->getContainedType(i); ++i)
+ ExtName += getTypeID(Ty);
+ ExtName += "_" + M->getName();
+
+ //cout << "Tried: '" << ExtName << "'\n";
+ ExFunc FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ExtName.c_str());
+ if (FnPtr == 0) // Try calling a generic function... if it exists...
+ FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ("lle_X_"+M->getName()).c_str());
+ if (FnPtr != 0)
+ Functions.insert(make_pair(M, FnPtr)); // Cache for later
+ return FnPtr;
+}
+
+void Interpreter::callExternalMethod(Method *M,
+ const vector<GenericValue> &ArgVals) {
+ // Do a lookup to see if the method is in our cache... this should just be a
+ // defered annotation!
+ map<const Method *, ExFunc>::iterator FI = Functions.find(M);
+ ExFunc Fn = (FI == Functions.end()) ? lookupMethod(M) : FI->second;
+ if (Fn == 0) {
+ cout << "Tried to execute an unknown external method: "
+ << M->getType()->getDescription() << " " << M->getName() << endl;
+ return;
+ }
+
+ // TODO: FIXME when types are not const!
+ GenericValue Result = Fn(const_cast<MethodType*>(M->getType()->isMethodType()), ArgVals);
+
+ // Copy the result back into the result variable if we are not returning void.
+ if (M->getReturnType() != Type::VoidTy) {
+ CallInst *Caller = ECStack.back().Caller;
+ if (Caller) {
+
+ } else {
+ // print it.
+ }
+ }
+}
+
+
+//===----------------------------------------------------------------------===//
+// Methods "exported" to the running application...
+//
+extern "C" { // Don't add C++ manglings to llvm mangling :)
+
+// Implement 'void print(X)' for every type...
+GenericValue lle_X_print(MethodType *M, const vector<GenericValue> &ArgVals) {
+ assert(ArgVals.size() == 1 && "generic print only takes one argument!");
+ Interpreter::printValue(M->getParamTypes()[0], ArgVals[0]);
+ return GenericValue();
+}
+
+// void "putchar"(sbyte)
+GenericValue lle_Vb_putchar(MethodType *M, const vector<GenericValue> &Args) {
+ cout << Args[0].SByteVal;
+ return GenericValue();
+}
+
+} // End extern "C"