blob: a54a6f1ced00cec9e65302a1aec087aa195f0f4d [file] [log] [blame]
Chris Lattner7720c8e2001-09-10 04:50:17 +00001//===-- 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>
Chris Lattnerc2593162001-10-27 08:28:11 +000017#include <math.h>
Chris Lattnerc063d382001-11-06 21:52:18 +000018#include <stdio.h>
Chris Lattner7720c8e2001-09-10 04:50:17 +000019
20typedef GenericValue (*ExFunc)(MethodType *, const vector<GenericValue> &);
21static map<const Method *, ExFunc> Functions;
Chris Lattner4721f132001-10-30 20:28:00 +000022static map<string, ExFunc> FuncNames;
Chris Lattner7720c8e2001-09-10 04:50:17 +000023
Chris Lattnere43db882001-10-27 04:15:57 +000024static Interpreter *TheInterpreter;
25
26// getCurrentExecutablePath() - Return the directory that the lli executable
27// lives in.
28//
29string Interpreter::getCurrentExecutablePath() const {
30 Dl_info Info;
31 if (dladdr(&TheInterpreter, &Info) == 0) return "";
32
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...
37
38 return LinkAddr;
39}
40
41
Chris Lattner7720c8e2001-09-10 04:50:17 +000042static 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';
61 default: return 'U';
62 }
63}
64
65static 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_";
Chris Lattneref9c23f2001-10-03 14:53:21 +000069 const MethodType *MT = M->getMethodType();
Chris Lattner7720c8e2001-09-10 04:50:17 +000070 for (unsigned i = 0; const Type *Ty = MT->getContainedType(i); ++i)
71 ExtName += getTypeID(Ty);
72 ExtName += "_" + M->getName();
73
74 //cout << "Tried: '" << ExtName << "'\n";
Chris Lattner4721f132001-10-30 20:28:00 +000075 ExFunc FnPtr = FuncNames[ExtName];
76 if (FnPtr == 0)
77 FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ExtName.c_str());
78 if (FnPtr == 0)
79 FnPtr = FuncNames["lle_X_"+M->getName()];
Chris Lattner7720c8e2001-09-10 04:50:17 +000080 if (FnPtr == 0) // Try calling a generic function... if it exists...
81 FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ("lle_X_"+M->getName()).c_str());
82 if (FnPtr != 0)
83 Functions.insert(make_pair(M, FnPtr)); // Cache for later
84 return FnPtr;
85}
86
Chris Lattner4721f132001-10-30 20:28:00 +000087GenericValue Interpreter::callExternalMethod(Method *M,
88 const vector<GenericValue> &ArgVals) {
Chris Lattnere43db882001-10-27 04:15:57 +000089 TheInterpreter = this;
90
Chris Lattner7720c8e2001-09-10 04:50:17 +000091 // 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;
95 if (Fn == 0) {
96 cout << "Tried to execute an unknown external method: "
97 << M->getType()->getDescription() << " " << M->getName() << endl;
Chris Lattner4721f132001-10-30 20:28:00 +000098 return GenericValue();
Chris Lattner7720c8e2001-09-10 04:50:17 +000099 }
100
101 // TODO: FIXME when types are not const!
Chris Lattneref9c23f2001-10-03 14:53:21 +0000102 GenericValue Result = Fn(const_cast<MethodType*>(M->getMethodType()),ArgVals);
Chris Lattner4721f132001-10-30 20:28:00 +0000103 return Result;
Chris Lattner7720c8e2001-09-10 04:50:17 +0000104}
105
106
107//===----------------------------------------------------------------------===//
108// Methods "exported" to the running application...
109//
110extern "C" { // Don't add C++ manglings to llvm mangling :)
111
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000112// Implement void printstr([ubyte {x N}] *)
113GenericValue 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();
117}
118
Chris Lattner7720c8e2001-09-10 04:50:17 +0000119// Implement 'void print(X)' for every type...
120GenericValue lle_X_print(MethodType *M, const vector<GenericValue> &ArgVals) {
121 assert(ArgVals.size() == 1 && "generic print only takes one argument!");
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000122
123 Interpreter::print(M->getParamTypes()[0], ArgVals[0]);
124 return GenericValue();
125}
126
127// Implement 'void printVal(X)' for every type...
128GenericValue lle_X_printVal(MethodType *M, const vector<GenericValue> &ArgVal) {
129 assert(ArgVal.size() == 1 && "generic print only takes one argument!");
130
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000131 // Specialize print([ubyte {x N} ] *) and print(sbyte *)
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000132 if (PointerType *PTy = dyn_cast<PointerType>(M->getParamTypes()[0].get()))
Chris Lattner7a176752001-12-04 00:03:30 +0000133 if (PTy->getElementType() == Type::SByteTy ||
134 isa<ArrayType>(PTy->getElementType())) {
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000135 return lle_VP_printstr(M, ArgVal);
136 }
137
138 Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);
Chris Lattner7720c8e2001-09-10 04:50:17 +0000139 return GenericValue();
140}
141
Vikram S. Adve3eb60f82001-10-28 20:52:27 +0000142// Implement 'void printString(X)'
143// Argument must be [ubyte {x N} ] * or sbyte *
144GenericValue 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);
147}
148
149// Implement 'void print<TYPE>(X)' for each primitive type or pointer type
150#define PRINT_TYPE_FUNC(TYPENAME,TYPEID) \
Chris Lattner316a65b2001-10-28 22:38:22 +0000151 GenericValue lle_X_print##TYPENAME(MethodType *M,\
152 const vector<GenericValue> &ArgVal) {\
Vikram S. Adve3eb60f82001-10-28 20:52:27 +0000153 assert(ArgVal.size() == 1 && "generic print only takes one argument!");\
Chris Lattner69b5ce92001-11-26 19:19:27 +0000154 assert(M->getParamTypes()[0].get()->getPrimitiveID() == Type::TYPEID);\
Vikram S. Adve3eb60f82001-10-28 20:52:27 +0000155 Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);\
156 return GenericValue();\
157 }
158
Chris Lattner4721f132001-10-30 20:28:00 +0000159PRINT_TYPE_FUNC(SByte, SByteTyID)
Vikram S. Adve3eb60f82001-10-28 20:52:27 +0000160PRINT_TYPE_FUNC(UByte, UByteTyID)
161PRINT_TYPE_FUNC(Short, ShortTyID)
162PRINT_TYPE_FUNC(UShort, UShortTyID)
163PRINT_TYPE_FUNC(Int, IntTyID)
164PRINT_TYPE_FUNC(UInt, UIntTyID)
165PRINT_TYPE_FUNC(Long, LongTyID)
166PRINT_TYPE_FUNC(ULong, ULongTyID)
167PRINT_TYPE_FUNC(Float, FloatTyID)
168PRINT_TYPE_FUNC(Double, DoubleTyID)
169PRINT_TYPE_FUNC(Pointer, PointerTyID)
170
171
Chris Lattner7720c8e2001-09-10 04:50:17 +0000172// void "putchar"(sbyte)
173GenericValue lle_Vb_putchar(MethodType *M, const vector<GenericValue> &Args) {
174 cout << Args[0].SByteVal;
175 return GenericValue();
176}
177
Chris Lattnere43db882001-10-27 04:15:57 +0000178// int "putchar"(int)
179GenericValue lle_ii_putchar(MethodType *M, const vector<GenericValue> &Args) {
180 cout << ((char)Args[0].IntVal) << flush;
181 return Args[0];
182}
183
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000184// void "putchar"(ubyte)
185GenericValue lle_VB_putchar(MethodType *M, const vector<GenericValue> &Args) {
Chris Lattnere43db882001-10-27 04:15:57 +0000186 cout << Args[0].SByteVal << flush;
187 return Args[0];
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000188}
189
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000190// void "__main"()
191GenericValue lle_V___main(MethodType *M, const vector<GenericValue> &Args) {
192 return GenericValue();
193}
194
Chris Lattnere43db882001-10-27 04:15:57 +0000195// void "exit"(int)
Chris Lattner0f279b22001-11-03 10:15:32 +0000196GenericValue lle_X_exit(MethodType *M, const vector<GenericValue> &Args) {
Chris Lattnere43db882001-10-27 04:15:57 +0000197 TheInterpreter->exitCalled(Args[0]);
198 return GenericValue();
199}
200
Chris Lattnerc2593162001-10-27 08:28:11 +0000201// void *malloc(uint)
Chris Lattner0f279b22001-11-03 10:15:32 +0000202GenericValue lle_X_malloc(MethodType *M, const vector<GenericValue> &Args) {
Chris Lattner4721f132001-10-30 20:28:00 +0000203 assert(Args.size() == 1 && "Malloc expects one argument!");
Chris Lattnerc2593162001-10-27 08:28:11 +0000204 GenericValue GV;
Chris Lattnerea38c0e2001-11-07 19:46:27 +0000205 GV.PointerVal = (PointerTy)malloc(Args[0].UIntVal);
Chris Lattnerc2593162001-10-27 08:28:11 +0000206 return GV;
207}
208
209// void free(void *)
Chris Lattner0f279b22001-11-03 10:15:32 +0000210GenericValue lle_X_free(MethodType *M, const vector<GenericValue> &Args) {
Chris Lattnerc063d382001-11-06 21:52:18 +0000211 assert(Args.size() == 1);
Chris Lattner4721f132001-10-30 20:28:00 +0000212 free((void*)Args[0].PointerVal);
Chris Lattnerc2593162001-10-27 08:28:11 +0000213 return GenericValue();
214}
215
Chris Lattner782b9392001-11-26 18:18:18 +0000216// int atoi(char *)
217GenericValue lle_X_atoi(MethodType *M, const vector<GenericValue> &Args) {
218 assert(Args.size() == 1);
219 GenericValue GV;
220 GV.IntVal = atoi((char*)Args[0].PointerVal);
221 return GV;
222}
223
Chris Lattnerc2593162001-10-27 08:28:11 +0000224// double pow(double, double)
Chris Lattner0f279b22001-11-03 10:15:32 +0000225GenericValue lle_X_pow(MethodType *M, const vector<GenericValue> &Args) {
Chris Lattnerc063d382001-11-06 21:52:18 +0000226 assert(Args.size() == 2);
Chris Lattnerc2593162001-10-27 08:28:11 +0000227 GenericValue GV;
Chris Lattner08845a22001-10-29 20:27:45 +0000228 GV.DoubleVal = pow(Args[0].DoubleVal, Args[1].DoubleVal);
Chris Lattnerc2593162001-10-27 08:28:11 +0000229 return GV;
230}
231
Chris Lattnerc063d382001-11-06 21:52:18 +0000232// double sqrt(double)
233GenericValue lle_X_sqrt(MethodType *M, const vector<GenericValue> &Args) {
234 assert(Args.size() == 1);
235 GenericValue GV;
236 GV.DoubleVal = sqrt(Args[0].DoubleVal);
237 return GV;
238}
Chris Lattnerc2593162001-10-27 08:28:11 +0000239
Chris Lattner86790052001-11-06 22:53:25 +0000240// double log(double)
241GenericValue lle_X_log(MethodType *M, const vector<GenericValue> &Args) {
242 assert(Args.size() == 1);
243 GenericValue GV;
244 GV.DoubleVal = log(Args[0].DoubleVal);
245 return GV;
246}
247
Chris Lattner782b9392001-11-26 18:18:18 +0000248// double floor(double)
249GenericValue lle_X_floor(MethodType *M, const vector<GenericValue> &Args) {
250 assert(Args.size() == 1);
251 GenericValue GV;
252 GV.DoubleVal = floor(Args[0].DoubleVal);
253 return GV;
254}
255
Chris Lattner86790052001-11-06 22:53:25 +0000256// double drand48()
257GenericValue lle_X_drand48(MethodType *M, const vector<GenericValue> &Args) {
258 assert(Args.size() == 0);
259 GenericValue GV;
260 GV.DoubleVal = drand48();
261 return GV;
262}
263
Chris Lattner1b600142001-11-13 05:46:08 +0000264// long lrand48()
265GenericValue lle_X_lrand48(MethodType *M, const vector<GenericValue> &Args) {
266 assert(Args.size() == 0);
267 GenericValue GV;
268 GV.IntVal = lrand48();
269 return GV;
270}
271
272// void srand48(long)
273GenericValue lle_X_srand48(MethodType *M, const vector<GenericValue> &Args) {
274 assert(Args.size() == 1);
275 srand48(Args[0].IntVal);
276 return GenericValue();
277}
278
Chris Lattner782b9392001-11-26 18:18:18 +0000279// void srand(uint)
280GenericValue lle_X_srand(MethodType *M, const vector<GenericValue> &Args) {
281 assert(Args.size() == 1);
282 srand(Args[0].UIntVal);
283 return GenericValue();
284}
Chris Lattner86790052001-11-06 22:53:25 +0000285
Chris Lattnere7c6f722001-12-13 00:43:47 +0000286// int sprintf(sbyte *, sbyte *, ...) - a very rough implementation to make
287// output useful.
288GenericValue lle_X_sprintf(MethodType *M, const vector<GenericValue> &Args) {
289 char *OutputBuffer = (char *)Args[0].PointerVal;
290 const char *FmtStr = (const char *)Args[1].PointerVal;
291 unsigned ArgNo = 2;
Chris Lattner08845a22001-10-29 20:27:45 +0000292
293 // printf should return # chars printed. This is completely incorrect, but
294 // close enough for now.
295 GenericValue GV; GV.IntVal = strlen(FmtStr);
296 while (1) {
297 switch (*FmtStr) {
298 case 0: return GV; // Null terminator...
299 default: // Normal nonspecial character
Chris Lattnere7c6f722001-12-13 00:43:47 +0000300 sprintf(OutputBuffer++, "%c", *FmtStr++);
Chris Lattner08845a22001-10-29 20:27:45 +0000301 break;
302 case '\\': { // Handle escape codes
Chris Lattnere7c6f722001-12-13 00:43:47 +0000303 sprintf(OutputBuffer, "%c%c", *FmtStr, *(FmtStr+1));
304 FmtStr += 2; OutputBuffer += 2;
Chris Lattner08845a22001-10-29 20:27:45 +0000305 break;
306 }
307 case '%': { // Handle format specifiers
Chris Lattnerea38c0e2001-11-07 19:46:27 +0000308 char FmtBuf[100] = "", Buffer[1000] = "";
309 char *FB = FmtBuf;
310 *FB++ = *FmtStr++;
311 char Last = *FB++ = *FmtStr++;
312 unsigned HowLong = 0;
313 while (Last != 'c' && Last != 'd' && Last != 'i' && Last != 'u' &&
314 Last != 'o' && Last != 'x' && Last != 'X' && Last != 'e' &&
315 Last != 'E' && Last != 'g' && Last != 'G' && Last != 'f' &&
316 Last != 'p' && Last != 's' && Last != '%') {
317 if (Last == 'l' || Last == 'L') HowLong++; // Keep track of l's
318 Last = *FB++ = *FmtStr++;
Chris Lattner08845a22001-10-29 20:27:45 +0000319 }
Chris Lattnerea38c0e2001-11-07 19:46:27 +0000320 *FB = 0;
321
322 switch (Last) {
323 case '%':
324 sprintf(Buffer, FmtBuf); break;
325 case 'c':
326 sprintf(Buffer, FmtBuf, Args[ArgNo++].SByteVal); break;
327 case 'd': case 'i':
328 case 'u': case 'o':
329 case 'x': case 'X':
330 if (HowLong == 2)
331 sprintf(Buffer, FmtBuf, Args[ArgNo++].ULongVal);
332 else
333 sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal); break;
334 case 'e': case 'E': case 'g': case 'G': case 'f':
335 sprintf(Buffer, FmtBuf, Args[ArgNo++].DoubleVal); break;
336 case 'p':
337 sprintf(Buffer, FmtBuf, (void*)Args[ArgNo++].PointerVal); break;
338 case 's':
339 sprintf(Buffer, FmtBuf, (char*)Args[ArgNo++].PointerVal); break;
340 default: cout << "<unknown printf code '" << *FmtStr << "'!>";
341 ArgNo++; break;
Chris Lattner08845a22001-10-29 20:27:45 +0000342 }
Chris Lattnere7c6f722001-12-13 00:43:47 +0000343 strcpy(OutputBuffer, Buffer);
344 OutputBuffer += strlen(Buffer);
Chris Lattnerea38c0e2001-11-07 19:46:27 +0000345 }
Chris Lattner08845a22001-10-29 20:27:45 +0000346 break;
347 }
Chris Lattner08845a22001-10-29 20:27:45 +0000348 }
349}
350
Chris Lattnere7c6f722001-12-13 00:43:47 +0000351// int printf(sbyte *, ...) - a very rough implementation to make output useful.
352GenericValue lle_X_printf(MethodType *M, const vector<GenericValue> &Args) {
353 char Buffer[10000];
354 vector<GenericValue> NewArgs;
355 GenericValue GV; GV.PointerVal = (PointerTy)Buffer;
356 NewArgs.push_back(GV);
357 NewArgs.insert(NewArgs.end(), Args.begin(), Args.end());
358 GV = lle_X_sprintf(M, NewArgs);
359 cout << Buffer;
360 return GV;
361}
362
363
Chris Lattner7720c8e2001-09-10 04:50:17 +0000364} // End extern "C"
Chris Lattner4721f132001-10-30 20:28:00 +0000365
366
367void Interpreter::initializeExternalMethods() {
368 FuncNames["lle_VP_printstr"] = lle_VP_printstr;
369 FuncNames["lle_X_print"] = lle_X_print;
370 FuncNames["lle_X_printVal"] = lle_X_printVal;
371 FuncNames["lle_X_printString"] = lle_X_printString;
372 FuncNames["lle_X_printUByte"] = lle_X_printUByte;
373 FuncNames["lle_X_printSByte"] = lle_X_printSByte;
374 FuncNames["lle_X_printUShort"] = lle_X_printUShort;
375 FuncNames["lle_X_printShort"] = lle_X_printShort;
376 FuncNames["lle_X_printInt"] = lle_X_printInt;
377 FuncNames["lle_X_printUInt"] = lle_X_printUInt;
378 FuncNames["lle_X_printLong"] = lle_X_printLong;
379 FuncNames["lle_X_printULong"] = lle_X_printULong;
380 FuncNames["lle_X_printFloat"] = lle_X_printFloat;
381 FuncNames["lle_X_printDouble"] = lle_X_printDouble;
382 FuncNames["lle_X_printPointer"] = lle_X_printPointer;
Chris Lattner0f279b22001-11-03 10:15:32 +0000383 FuncNames["lle_Vb_putchar"] = lle_Vb_putchar;
384 FuncNames["lle_ii_putchar"] = lle_ii_putchar;
385 FuncNames["lle_VB_putchar"] = lle_VB_putchar;
386 FuncNames["lle_V___main"] = lle_V___main;
387 FuncNames["lle_X_exit"] = lle_X_exit;
388 FuncNames["lle_X_malloc"] = lle_X_malloc;
389 FuncNames["lle_X_free"] = lle_X_free;
Chris Lattner782b9392001-11-26 18:18:18 +0000390 FuncNames["lle_X_atoi"] = lle_X_atoi;
Chris Lattner0f279b22001-11-03 10:15:32 +0000391 FuncNames["lle_X_pow"] = lle_X_pow;
Chris Lattner1b600142001-11-13 05:46:08 +0000392 FuncNames["lle_X_log"] = lle_X_log;
Chris Lattner782b9392001-11-26 18:18:18 +0000393 FuncNames["lle_X_floor"] = lle_X_floor;
394 FuncNames["lle_X_srand"] = lle_X_srand;
Chris Lattner1b600142001-11-13 05:46:08 +0000395 FuncNames["lle_X_drand48"] = lle_X_drand48;
396 FuncNames["lle_X_srand48"] = lle_X_srand48;
397 FuncNames["lle_X_lrand48"] = lle_X_lrand48;
Chris Lattnerc063d382001-11-06 21:52:18 +0000398 FuncNames["lle_X_sqrt"] = lle_X_sqrt;
Chris Lattner0f279b22001-11-03 10:15:32 +0000399 FuncNames["lle_X_printf"] = lle_X_printf;
Chris Lattnere7c6f722001-12-13 00:43:47 +0000400 FuncNames["lle_X_sprintf"] = lle_X_sprintf;
Chris Lattner4721f132001-10-30 20:28:00 +0000401}