* Implement exit() builtin function
[oota-llvm.git] / lib / ExecutionEngine / Interpreter / ExternalFunctions.cpp
1 //===-- ExternalMethods.cpp - Implement External Methods ------------------===//
2 // 
3 //  This file contains both code to deal with invoking "external" methods, but
4 //  also contains code that implements "exported" external methods. 
5 //
6 //  External methods in LLI are implemented by dlopen'ing the lli executable and
7 //  using dlsym to look op the methods that we want to invoke.  If a method is
8 //  found, then the arguments are mangled and passed in to the function call.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #include "Interpreter.h"
13 #include "llvm/DerivedTypes.h"
14 #include <map>
15 #include <dlfcn.h>
16 #include <link.h>
17
18 typedef GenericValue (*ExFunc)(MethodType *, const vector<GenericValue> &);
19 static map<const Method *, ExFunc> Functions;
20
21 static Interpreter *TheInterpreter;
22
23 // getCurrentExecutablePath() - Return the directory that the lli executable
24 // lives in.
25 //
26 string Interpreter::getCurrentExecutablePath() const {
27   Dl_info Info;
28   if (dladdr(&TheInterpreter, &Info) == 0) return "";
29   
30   string LinkAddr(Info.dli_fname);
31   unsigned SlashPos = LinkAddr.rfind('/');
32   if (SlashPos != string::npos)
33     LinkAddr.resize(SlashPos);    // Trim the executable name off...
34
35   return LinkAddr;
36 }
37
38
39 static char getTypeID(const Type *Ty) {
40   switch (Ty->getPrimitiveID()) {
41   case Type::VoidTyID:    return 'V';
42   case Type::BoolTyID:    return 'o';
43   case Type::UByteTyID:   return 'B';
44   case Type::SByteTyID:   return 'b';
45   case Type::UShortTyID:  return 'S';
46   case Type::ShortTyID:   return 's';
47   case Type::UIntTyID:    return 'I';
48   case Type::IntTyID:     return 'i';
49   case Type::ULongTyID:   return 'L';
50   case Type::LongTyID:    return 'l';
51   case Type::FloatTyID:   return 'F';
52   case Type::DoubleTyID:  return 'D';
53   case Type::PointerTyID: return 'P';
54   case Type::MethodTyID:  return 'M';
55   case Type::StructTyID:  return 'T';
56   case Type::ArrayTyID:   return 'A';
57   case Type::OpaqueTyID:  return 'O';
58   default: return 'U';
59   }
60 }
61
62 static ExFunc lookupMethod(const Method *M) {
63   // Function not found, look it up... start by figuring out what the
64   // composite function name should be.
65   string ExtName = "lle_";
66   const MethodType *MT = M->getMethodType();
67   for (unsigned i = 0; const Type *Ty = MT->getContainedType(i); ++i)
68     ExtName += getTypeID(Ty);
69   ExtName += "_" + M->getName();
70
71   //cout << "Tried: '" << ExtName << "'\n";
72   ExFunc FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ExtName.c_str());
73   if (FnPtr == 0)  // Try calling a generic function... if it exists...
74     FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ("lle_X_"+M->getName()).c_str());
75   if (FnPtr != 0)
76     Functions.insert(make_pair(M, FnPtr));  // Cache for later
77   return FnPtr;
78 }
79
80 void Interpreter::callExternalMethod(Method *M,
81                                      const vector<GenericValue> &ArgVals) {
82   TheInterpreter = this;
83
84   // Do a lookup to see if the method is in our cache... this should just be a
85   // defered annotation!
86   map<const Method *, ExFunc>::iterator FI = Functions.find(M);
87   ExFunc Fn = (FI == Functions.end()) ? lookupMethod(M) : FI->second;
88   if (Fn == 0) {
89     cout << "Tried to execute an unknown external method: "
90          << M->getType()->getDescription() << " " << M->getName() << endl;
91     return;
92   }
93
94   // TODO: FIXME when types are not const!
95   GenericValue Result = Fn(const_cast<MethodType*>(M->getMethodType()),ArgVals);
96   
97   // Copy the result back into the result variable if we are not returning void.
98   if (M->getReturnType() != Type::VoidTy) {
99     CallInst *Caller = ECStack.back().Caller;
100     if (Caller) {
101
102     } else {
103       // print it.
104     }
105   }
106 }
107
108
109 //===----------------------------------------------------------------------===//
110 //  Methods "exported" to the running application...
111 //
112 extern "C" {  // Don't add C++ manglings to llvm mangling :)
113
114 // Implement void printstr([ubyte {x N}] *)
115 GenericValue lle_VP_printstr(MethodType *M, const vector<GenericValue> &ArgVal){
116   assert(ArgVal.size() == 1 && "printstr only takes one argument!");
117   cout << (char*)ArgVal[0].PointerVal;
118   return GenericValue();
119 }
120
121 // Implement 'void print(X)' for every type...
122 GenericValue lle_X_print(MethodType *M, const vector<GenericValue> &ArgVals) {
123   assert(ArgVals.size() == 1 && "generic print only takes one argument!");
124
125   Interpreter::print(M->getParamTypes()[0], ArgVals[0]);
126   return GenericValue();
127 }
128
129 // Implement 'void printVal(X)' for every type...
130 GenericValue lle_X_printVal(MethodType *M, const vector<GenericValue> &ArgVal) {
131   assert(ArgVal.size() == 1 && "generic print only takes one argument!");
132
133   // Specialize print([ubyte {x N} ] *) and print(sbyte *)
134   if (PointerType *PTy = dyn_cast<PointerType>(M->getParamTypes()[0].get()))
135     if (PTy->getValueType() == Type::SByteTy ||
136         isa<ArrayType>(PTy->getValueType())) {
137       return lle_VP_printstr(M, ArgVal);
138     }
139
140   Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);
141   return GenericValue();
142 }
143
144 // void "putchar"(sbyte)
145 GenericValue lle_Vb_putchar(MethodType *M, const vector<GenericValue> &Args) {
146   cout << Args[0].SByteVal;
147   return GenericValue();
148 }
149
150 // int "putchar"(int)
151 GenericValue lle_ii_putchar(MethodType *M, const vector<GenericValue> &Args) {
152   cout << ((char)Args[0].IntVal) << flush;
153   return Args[0];
154 }
155
156 // void "putchar"(ubyte)
157 GenericValue lle_VB_putchar(MethodType *M, const vector<GenericValue> &Args) {
158   cout << Args[0].SByteVal << flush;
159   return Args[0];
160 }
161
162 // void "__main"()
163 GenericValue lle_V___main(MethodType *M, const vector<GenericValue> &Args) {
164   return GenericValue();
165 }
166
167 // void "exit"(int)
168 GenericValue lle_Vi_exit(MethodType *M, const vector<GenericValue> &Args) {
169   TheInterpreter->exitCalled(Args[0]);
170   return GenericValue();
171 }
172
173 } // End extern "C"