| //===-- 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->getMethodType(); | 
 |   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->getMethodType()),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 printstr([ubyte {x N}] *) | 
 | GenericValue lle_VP_printstr(MethodType *M, const vector<GenericValue> &ArgVal){ | 
 |   assert(ArgVal.size() == 1 && "printstr only takes one argument!"); | 
 |   cout << (char*)ArgVal[0].PointerVal; | 
 |   return GenericValue(); | 
 | } | 
 |  | 
 | // 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::print(M->getParamTypes()[0], ArgVals[0]); | 
 |   return GenericValue(); | 
 | } | 
 |  | 
 | // Implement 'void printVal(X)' for every type... | 
 | GenericValue lle_X_printVal(MethodType *M, const vector<GenericValue> &ArgVal) { | 
 |   assert(ArgVal.size() == 1 && "generic print only takes one argument!"); | 
 |  | 
 |   // Specialize print([ubyte {x N} ] *) | 
 |   if (PointerType *PTy = dyn_cast<PointerType>(M->getParamTypes()[0].get())) | 
 |     if (const ArrayType *ATy = dyn_cast<ArrayType>(PTy->getValueType())) { | 
 |       return lle_VP_printstr(M, ArgVal); | 
 |     } | 
 |  | 
 |   Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]); | 
 |   return GenericValue(); | 
 | } | 
 |  | 
 | // void "putchar"(sbyte) | 
 | GenericValue lle_Vb_putchar(MethodType *M, const vector<GenericValue> &Args) { | 
 |   cout << Args[0].SByteVal; | 
 |   return GenericValue(); | 
 | } | 
 |  | 
 | // void "putchar"(ubyte) | 
 | GenericValue lle_VB_putchar(MethodType *M, const vector<GenericValue> &Args) { | 
 |   cout << Args[0].UByteVal; | 
 |   return GenericValue(); | 
 | } | 
 |  | 
 | } // End extern "C" |