blob: 08158d2be576015543b6ac1290609459b5fbd193 [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 Lattnerf8f2afb2001-10-18 21:55:32 +0000133 if (PTy->getValueType() == Type::SByteTy ||
134 isa<ArrayType>(PTy->getValueType())) {
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 Lattner316a65b2001-10-28 22:38:22 +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 Lattner4721f132001-10-30 20:28:00 +0000205 GV.PointerVal = (uint64_t)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
216// double pow(double, double)
Chris Lattner0f279b22001-11-03 10:15:32 +0000217GenericValue lle_X_pow(MethodType *M, const vector<GenericValue> &Args) {
Chris Lattnerc063d382001-11-06 21:52:18 +0000218 assert(Args.size() == 2);
Chris Lattnerc2593162001-10-27 08:28:11 +0000219 GenericValue GV;
Chris Lattner08845a22001-10-29 20:27:45 +0000220 GV.DoubleVal = pow(Args[0].DoubleVal, Args[1].DoubleVal);
Chris Lattnerc2593162001-10-27 08:28:11 +0000221 return GV;
222}
223
Chris Lattnerc063d382001-11-06 21:52:18 +0000224// double sqrt(double)
225GenericValue lle_X_sqrt(MethodType *M, const vector<GenericValue> &Args) {
226 assert(Args.size() == 1);
227 GenericValue GV;
228 GV.DoubleVal = sqrt(Args[0].DoubleVal);
229 return GV;
230}
Chris Lattnerc2593162001-10-27 08:28:11 +0000231
Chris Lattner86790052001-11-06 22:53:25 +0000232// double log(double)
233GenericValue lle_X_log(MethodType *M, const vector<GenericValue> &Args) {
234 assert(Args.size() == 1);
235 GenericValue GV;
236 GV.DoubleVal = log(Args[0].DoubleVal);
237 return GV;
238}
239
240// double drand48()
241GenericValue lle_X_drand48(MethodType *M, const vector<GenericValue> &Args) {
242 assert(Args.size() == 0);
243 GenericValue GV;
244 GV.DoubleVal = drand48();
245 return GV;
246}
247
248
Chris Lattner08845a22001-10-29 20:27:45 +0000249// int printf(sbyte *, ...) - a very rough implementation to make output useful.
Chris Lattner0f279b22001-11-03 10:15:32 +0000250GenericValue lle_X_printf(MethodType *M, const vector<GenericValue> &Args) {
Chris Lattner08845a22001-10-29 20:27:45 +0000251 const char *FmtStr = (const char *)Args[0].PointerVal;
252 unsigned ArgNo = 1;
253
254 // printf should return # chars printed. This is completely incorrect, but
255 // close enough for now.
256 GenericValue GV; GV.IntVal = strlen(FmtStr);
257 while (1) {
258 switch (*FmtStr) {
259 case 0: return GV; // Null terminator...
260 default: // Normal nonspecial character
261 cout << *FmtStr++;
262 break;
263 case '\\': { // Handle escape codes
264 char Buffer[3];
265 Buffer[0] = *FmtStr++;
266 Buffer[1] = *FmtStr++;
267 Buffer[2] = 0;
268 cout << Buffer;
269 break;
270 }
271 case '%': { // Handle format specifiers
272 bool isLong = false;
273 ++FmtStr;
274 if (*FmtStr == 'l') {
275 isLong = true;
276 FmtStr++;
277 }
278
Chris Lattnerc063d382001-11-06 21:52:18 +0000279 if (*FmtStr == '%')
280 cout << *FmtStr; // %%
281 else {
282 char Fmt[] = "%d", Buffer[1000] = "";
283 Fmt[1] = *FmtStr;
284
285 switch (*FmtStr) {
286 case 'c':
287 sprintf(Buffer, Fmt, Args[ArgNo++].SByteVal); break;
288 case 'd': case 'i':
289 case 'u': case 'o':
290 case 'x': case 'X':
291 sprintf(Buffer, Fmt, Args[ArgNo++].IntVal); break;
292 case 'e': case 'E': case 'g': case 'G': case 'f':
293 sprintf(Buffer, Fmt, Args[ArgNo++].DoubleVal); break;
294 case 's': cout << (char*)Args[ArgNo++].PointerVal; break; // %s
295 default: cout << "<unknown printf code '" << *FmtStr << "'!>";
296 ArgNo++; break;
297 }
298 cout << Buffer;
Chris Lattner08845a22001-10-29 20:27:45 +0000299 }
300 ++FmtStr;
301 break;
302 }
303 }
304 }
305}
306
Chris Lattner7720c8e2001-09-10 04:50:17 +0000307} // End extern "C"
Chris Lattner4721f132001-10-30 20:28:00 +0000308
309
310void Interpreter::initializeExternalMethods() {
311 FuncNames["lle_VP_printstr"] = lle_VP_printstr;
312 FuncNames["lle_X_print"] = lle_X_print;
313 FuncNames["lle_X_printVal"] = lle_X_printVal;
314 FuncNames["lle_X_printString"] = lle_X_printString;
315 FuncNames["lle_X_printUByte"] = lle_X_printUByte;
316 FuncNames["lle_X_printSByte"] = lle_X_printSByte;
317 FuncNames["lle_X_printUShort"] = lle_X_printUShort;
318 FuncNames["lle_X_printShort"] = lle_X_printShort;
319 FuncNames["lle_X_printInt"] = lle_X_printInt;
320 FuncNames["lle_X_printUInt"] = lle_X_printUInt;
321 FuncNames["lle_X_printLong"] = lle_X_printLong;
322 FuncNames["lle_X_printULong"] = lle_X_printULong;
323 FuncNames["lle_X_printFloat"] = lle_X_printFloat;
324 FuncNames["lle_X_printDouble"] = lle_X_printDouble;
325 FuncNames["lle_X_printPointer"] = lle_X_printPointer;
Chris Lattner0f279b22001-11-03 10:15:32 +0000326 FuncNames["lle_Vb_putchar"] = lle_Vb_putchar;
327 FuncNames["lle_ii_putchar"] = lle_ii_putchar;
328 FuncNames["lle_VB_putchar"] = lle_VB_putchar;
329 FuncNames["lle_V___main"] = lle_V___main;
330 FuncNames["lle_X_exit"] = lle_X_exit;
331 FuncNames["lle_X_malloc"] = lle_X_malloc;
332 FuncNames["lle_X_free"] = lle_X_free;
333 FuncNames["lle_X_pow"] = lle_X_pow;
Chris Lattnerc063d382001-11-06 21:52:18 +0000334 FuncNames["lle_X_sqrt"] = lle_X_sqrt;
Chris Lattner0f279b22001-11-03 10:15:32 +0000335 FuncNames["lle_X_printf"] = lle_X_printf;
Chris Lattner4721f132001-10-30 20:28:00 +0000336}