1 //===-- ExternalMethods.cpp - Implement External Methods ------------------===//
3 // This file contains both code to deal with invoking "external" methods, but
4 // also contains code that implements "exported" external methods.
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.
10 //===----------------------------------------------------------------------===//
12 #include "Interpreter.h"
13 #include "llvm/DerivedTypes.h"
20 typedef GenericValue (*ExFunc)(MethodType *, const vector<GenericValue> &);
21 static map<const Method *, ExFunc> Functions;
22 static map<string, ExFunc> FuncNames;
24 static Interpreter *TheInterpreter;
26 // getCurrentExecutablePath() - Return the directory that the lli executable
29 string Interpreter::getCurrentExecutablePath() const {
31 if (dladdr(&TheInterpreter, &Info) == 0) return "";
33 string LinkAddr(Info.dli_fname);
34 unsigned SlashPos = LinkAddr.rfind('/');
35 if (SlashPos != string::npos)
36 LinkAddr.resize(SlashPos); // Trim the executable name off...
42 static char getTypeID(const Type *Ty) {
43 switch (Ty->getPrimitiveID()) {
44 case Type::VoidTyID: return 'V';
45 case Type::BoolTyID: return 'o';
46 case Type::UByteTyID: return 'B';
47 case Type::SByteTyID: return 'b';
48 case Type::UShortTyID: return 'S';
49 case Type::ShortTyID: return 's';
50 case Type::UIntTyID: return 'I';
51 case Type::IntTyID: return 'i';
52 case Type::ULongTyID: return 'L';
53 case Type::LongTyID: return 'l';
54 case Type::FloatTyID: return 'F';
55 case Type::DoubleTyID: return 'D';
56 case Type::PointerTyID: return 'P';
57 case Type::MethodTyID: return 'M';
58 case Type::StructTyID: return 'T';
59 case Type::ArrayTyID: return 'A';
60 case Type::OpaqueTyID: return 'O';
65 static ExFunc lookupMethod(const Method *M) {
66 // Function not found, look it up... start by figuring out what the
67 // composite function name should be.
68 string ExtName = "lle_";
69 const MethodType *MT = M->getMethodType();
70 for (unsigned i = 0; const Type *Ty = MT->getContainedType(i); ++i)
71 ExtName += getTypeID(Ty);
72 ExtName += "_" + M->getName();
74 //cout << "Tried: '" << ExtName << "'\n";
75 ExFunc FnPtr = FuncNames[ExtName];
77 FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ExtName.c_str());
79 FnPtr = FuncNames["lle_X_"+M->getName()];
80 if (FnPtr == 0) // Try calling a generic function... if it exists...
81 FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ("lle_X_"+M->getName()).c_str());
83 Functions.insert(make_pair(M, FnPtr)); // Cache for later
87 GenericValue Interpreter::callExternalMethod(Method *M,
88 const vector<GenericValue> &ArgVals) {
89 TheInterpreter = this;
91 // Do a lookup to see if the method is in our cache... this should just be a
92 // defered annotation!
93 map<const Method *, ExFunc>::iterator FI = Functions.find(M);
94 ExFunc Fn = (FI == Functions.end()) ? lookupMethod(M) : FI->second;
96 cout << "Tried to execute an unknown external method: "
97 << M->getType()->getDescription() << " " << M->getName() << endl;
98 return GenericValue();
101 // TODO: FIXME when types are not const!
102 GenericValue Result = Fn(const_cast<MethodType*>(M->getMethodType()),ArgVals);
107 //===----------------------------------------------------------------------===//
108 // Methods "exported" to the running application...
110 extern "C" { // Don't add C++ manglings to llvm mangling :)
112 // Implement void printstr([ubyte {x N}] *)
113 GenericValue lle_VP_printstr(MethodType *M, const vector<GenericValue> &ArgVal){
114 assert(ArgVal.size() == 1 && "printstr only takes one argument!");
115 cout << (char*)ArgVal[0].PointerVal;
116 return GenericValue();
119 // Implement 'void print(X)' for every type...
120 GenericValue lle_X_print(MethodType *M, const vector<GenericValue> &ArgVals) {
121 assert(ArgVals.size() == 1 && "generic print only takes one argument!");
123 Interpreter::print(M->getParamTypes()[0], ArgVals[0]);
124 return GenericValue();
127 // Implement 'void printVal(X)' for every type...
128 GenericValue lle_X_printVal(MethodType *M, const vector<GenericValue> &ArgVal) {
129 assert(ArgVal.size() == 1 && "generic print only takes one argument!");
131 // Specialize print([ubyte {x N} ] *) and print(sbyte *)
132 if (PointerType *PTy = dyn_cast<PointerType>(M->getParamTypes()[0].get()))
133 if (PTy->getValueType() == Type::SByteTy ||
134 isa<ArrayType>(PTy->getValueType())) {
135 return lle_VP_printstr(M, ArgVal);
138 Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);
139 return GenericValue();
142 // Implement 'void printString(X)'
143 // Argument must be [ubyte {x N} ] * or sbyte *
144 GenericValue lle_X_printString(MethodType *M, const vector<GenericValue> &ArgVal) {
145 assert(ArgVal.size() == 1 && "generic print only takes one argument!");
146 return lle_VP_printstr(M, ArgVal);
149 // Implement 'void print<TYPE>(X)' for each primitive type or pointer type
150 #define PRINT_TYPE_FUNC(TYPENAME,TYPEID) \
151 GenericValue lle_X_print##TYPENAME(MethodType *M,\
152 const vector<GenericValue> &ArgVal) {\
153 assert(ArgVal.size() == 1 && "generic print only takes one argument!");\
154 assert(M->getParamTypes()[0].get()->getPrimitiveID() == Type::##TYPEID);\
155 Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);\
156 return GenericValue();\
159 PRINT_TYPE_FUNC(SByte, SByteTyID)
160 PRINT_TYPE_FUNC(UByte, UByteTyID)
161 PRINT_TYPE_FUNC(Short, ShortTyID)
162 PRINT_TYPE_FUNC(UShort, UShortTyID)
163 PRINT_TYPE_FUNC(Int, IntTyID)
164 PRINT_TYPE_FUNC(UInt, UIntTyID)
165 PRINT_TYPE_FUNC(Long, LongTyID)
166 PRINT_TYPE_FUNC(ULong, ULongTyID)
167 PRINT_TYPE_FUNC(Float, FloatTyID)
168 PRINT_TYPE_FUNC(Double, DoubleTyID)
169 PRINT_TYPE_FUNC(Pointer, PointerTyID)
172 // void "putchar"(sbyte)
173 GenericValue lle_Vb_putchar(MethodType *M, const vector<GenericValue> &Args) {
174 cout << Args[0].SByteVal;
175 return GenericValue();
178 // int "putchar"(int)
179 GenericValue lle_ii_putchar(MethodType *M, const vector<GenericValue> &Args) {
180 cout << ((char)Args[0].IntVal) << flush;
184 // void "putchar"(ubyte)
185 GenericValue lle_VB_putchar(MethodType *M, const vector<GenericValue> &Args) {
186 cout << Args[0].SByteVal << flush;
191 GenericValue lle_V___main(MethodType *M, const vector<GenericValue> &Args) {
192 return GenericValue();
196 GenericValue lle_X_exit(MethodType *M, const vector<GenericValue> &Args) {
197 TheInterpreter->exitCalled(Args[0]);
198 return GenericValue();
201 // void *malloc(uint)
202 GenericValue lle_X_malloc(MethodType *M, const vector<GenericValue> &Args) {
203 assert(Args.size() == 1 && "Malloc expects one argument!");
205 GV.PointerVal = (PointerTy)malloc(Args[0].UIntVal);
210 GenericValue lle_X_free(MethodType *M, const vector<GenericValue> &Args) {
211 assert(Args.size() == 1);
212 free((void*)Args[0].PointerVal);
213 return GenericValue();
217 GenericValue lle_X_atoi(MethodType *M, const vector<GenericValue> &Args) {
218 assert(Args.size() == 1);
220 GV.IntVal = atoi((char*)Args[0].PointerVal);
224 // double pow(double, double)
225 GenericValue lle_X_pow(MethodType *M, const vector<GenericValue> &Args) {
226 assert(Args.size() == 2);
228 GV.DoubleVal = pow(Args[0].DoubleVal, Args[1].DoubleVal);
232 // double sqrt(double)
233 GenericValue lle_X_sqrt(MethodType *M, const vector<GenericValue> &Args) {
234 assert(Args.size() == 1);
236 GV.DoubleVal = sqrt(Args[0].DoubleVal);
240 // double log(double)
241 GenericValue lle_X_log(MethodType *M, const vector<GenericValue> &Args) {
242 assert(Args.size() == 1);
244 GV.DoubleVal = log(Args[0].DoubleVal);
248 // double floor(double)
249 GenericValue lle_X_floor(MethodType *M, const vector<GenericValue> &Args) {
250 assert(Args.size() == 1);
252 GV.DoubleVal = floor(Args[0].DoubleVal);
257 GenericValue lle_X_drand48(MethodType *M, const vector<GenericValue> &Args) {
258 assert(Args.size() == 0);
260 GV.DoubleVal = drand48();
265 GenericValue lle_X_lrand48(MethodType *M, const vector<GenericValue> &Args) {
266 assert(Args.size() == 0);
268 GV.IntVal = lrand48();
272 // void srand48(long)
273 GenericValue lle_X_srand48(MethodType *M, const vector<GenericValue> &Args) {
274 assert(Args.size() == 1);
275 srand48(Args[0].IntVal);
276 return GenericValue();
280 GenericValue lle_X_srand(MethodType *M, const vector<GenericValue> &Args) {
281 assert(Args.size() == 1);
282 srand(Args[0].UIntVal);
283 return GenericValue();
286 // int printf(sbyte *, ...) - a very rough implementation to make output useful.
287 GenericValue lle_X_printf(MethodType *M, const vector<GenericValue> &Args) {
288 const char *FmtStr = (const char *)Args[0].PointerVal;
291 // printf should return # chars printed. This is completely incorrect, but
292 // close enough for now.
293 GenericValue GV; GV.IntVal = strlen(FmtStr);
296 case 0: return GV; // Null terminator...
297 default: // Normal nonspecial character
300 case '\\': { // Handle escape codes
302 Buffer[0] = *FmtStr++;
303 Buffer[1] = *FmtStr++;
308 case '%': { // Handle format specifiers
309 char FmtBuf[100] = "", Buffer[1000] = "";
312 char Last = *FB++ = *FmtStr++;
313 unsigned HowLong = 0;
314 while (Last != 'c' && Last != 'd' && Last != 'i' && Last != 'u' &&
315 Last != 'o' && Last != 'x' && Last != 'X' && Last != 'e' &&
316 Last != 'E' && Last != 'g' && Last != 'G' && Last != 'f' &&
317 Last != 'p' && Last != 's' && Last != '%') {
318 if (Last == 'l' || Last == 'L') HowLong++; // Keep track of l's
319 Last = *FB++ = *FmtStr++;
325 sprintf(Buffer, FmtBuf); break;
327 sprintf(Buffer, FmtBuf, Args[ArgNo++].SByteVal); break;
332 sprintf(Buffer, FmtBuf, Args[ArgNo++].ULongVal);
334 sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal); break;
335 case 'e': case 'E': case 'g': case 'G': case 'f':
336 sprintf(Buffer, FmtBuf, Args[ArgNo++].DoubleVal); break;
338 sprintf(Buffer, FmtBuf, (void*)Args[ArgNo++].PointerVal); break;
340 sprintf(Buffer, FmtBuf, (char*)Args[ArgNo++].PointerVal); break;
341 default: cout << "<unknown printf code '" << *FmtStr << "'!>";
354 void Interpreter::initializeExternalMethods() {
355 FuncNames["lle_VP_printstr"] = lle_VP_printstr;
356 FuncNames["lle_X_print"] = lle_X_print;
357 FuncNames["lle_X_printVal"] = lle_X_printVal;
358 FuncNames["lle_X_printString"] = lle_X_printString;
359 FuncNames["lle_X_printUByte"] = lle_X_printUByte;
360 FuncNames["lle_X_printSByte"] = lle_X_printSByte;
361 FuncNames["lle_X_printUShort"] = lle_X_printUShort;
362 FuncNames["lle_X_printShort"] = lle_X_printShort;
363 FuncNames["lle_X_printInt"] = lle_X_printInt;
364 FuncNames["lle_X_printUInt"] = lle_X_printUInt;
365 FuncNames["lle_X_printLong"] = lle_X_printLong;
366 FuncNames["lle_X_printULong"] = lle_X_printULong;
367 FuncNames["lle_X_printFloat"] = lle_X_printFloat;
368 FuncNames["lle_X_printDouble"] = lle_X_printDouble;
369 FuncNames["lle_X_printPointer"] = lle_X_printPointer;
370 FuncNames["lle_Vb_putchar"] = lle_Vb_putchar;
371 FuncNames["lle_ii_putchar"] = lle_ii_putchar;
372 FuncNames["lle_VB_putchar"] = lle_VB_putchar;
373 FuncNames["lle_V___main"] = lle_V___main;
374 FuncNames["lle_X_exit"] = lle_X_exit;
375 FuncNames["lle_X_malloc"] = lle_X_malloc;
376 FuncNames["lle_X_free"] = lle_X_free;
377 FuncNames["lle_X_atoi"] = lle_X_atoi;
378 FuncNames["lle_X_pow"] = lle_X_pow;
379 FuncNames["lle_X_log"] = lle_X_log;
380 FuncNames["lle_X_floor"] = lle_X_floor;
381 FuncNames["lle_X_srand"] = lle_X_srand;
382 FuncNames["lle_X_drand48"] = lle_X_drand48;
383 FuncNames["lle_X_srand48"] = lle_X_srand48;
384 FuncNames["lle_X_lrand48"] = lle_X_lrand48;
385 FuncNames["lle_X_sqrt"] = lle_X_sqrt;
386 FuncNames["lle_X_printf"] = lle_X_printf;