blob: a6a75f635d9c16f15c240a516c904dbb6c1645c5 [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 Lattner7720c8e2001-09-10 04:50:17 +000018
19typedef GenericValue (*ExFunc)(MethodType *, const vector<GenericValue> &);
20static map<const Method *, ExFunc> Functions;
Chris Lattner4721f132001-10-30 20:28:00 +000021static map<string, ExFunc> FuncNames;
Chris Lattner7720c8e2001-09-10 04:50:17 +000022
Chris Lattnere43db882001-10-27 04:15:57 +000023static Interpreter *TheInterpreter;
24
25// getCurrentExecutablePath() - Return the directory that the lli executable
26// lives in.
27//
28string Interpreter::getCurrentExecutablePath() const {
29 Dl_info Info;
30 if (dladdr(&TheInterpreter, &Info) == 0) return "";
31
32 string LinkAddr(Info.dli_fname);
33 unsigned SlashPos = LinkAddr.rfind('/');
34 if (SlashPos != string::npos)
35 LinkAddr.resize(SlashPos); // Trim the executable name off...
36
37 return LinkAddr;
38}
39
40
Chris Lattner7720c8e2001-09-10 04:50:17 +000041static char getTypeID(const Type *Ty) {
42 switch (Ty->getPrimitiveID()) {
43 case Type::VoidTyID: return 'V';
44 case Type::BoolTyID: return 'o';
45 case Type::UByteTyID: return 'B';
46 case Type::SByteTyID: return 'b';
47 case Type::UShortTyID: return 'S';
48 case Type::ShortTyID: return 's';
49 case Type::UIntTyID: return 'I';
50 case Type::IntTyID: return 'i';
51 case Type::ULongTyID: return 'L';
52 case Type::LongTyID: return 'l';
53 case Type::FloatTyID: return 'F';
54 case Type::DoubleTyID: return 'D';
55 case Type::PointerTyID: return 'P';
56 case Type::MethodTyID: return 'M';
57 case Type::StructTyID: return 'T';
58 case Type::ArrayTyID: return 'A';
59 case Type::OpaqueTyID: return 'O';
60 default: return 'U';
61 }
62}
63
64static ExFunc lookupMethod(const Method *M) {
65 // Function not found, look it up... start by figuring out what the
66 // composite function name should be.
67 string ExtName = "lle_";
Chris Lattneref9c23f2001-10-03 14:53:21 +000068 const MethodType *MT = M->getMethodType();
Chris Lattner7720c8e2001-09-10 04:50:17 +000069 for (unsigned i = 0; const Type *Ty = MT->getContainedType(i); ++i)
70 ExtName += getTypeID(Ty);
71 ExtName += "_" + M->getName();
72
73 //cout << "Tried: '" << ExtName << "'\n";
Chris Lattner4721f132001-10-30 20:28:00 +000074 ExFunc FnPtr = FuncNames[ExtName];
75 if (FnPtr == 0)
76 FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ExtName.c_str());
77 if (FnPtr == 0)
78 FnPtr = FuncNames["lle_X_"+M->getName()];
Chris Lattner7720c8e2001-09-10 04:50:17 +000079 if (FnPtr == 0) // Try calling a generic function... if it exists...
80 FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ("lle_X_"+M->getName()).c_str());
81 if (FnPtr != 0)
82 Functions.insert(make_pair(M, FnPtr)); // Cache for later
83 return FnPtr;
84}
85
Chris Lattner4721f132001-10-30 20:28:00 +000086GenericValue Interpreter::callExternalMethod(Method *M,
87 const vector<GenericValue> &ArgVals) {
Chris Lattnere43db882001-10-27 04:15:57 +000088 TheInterpreter = this;
89
Chris Lattner7720c8e2001-09-10 04:50:17 +000090 // Do a lookup to see if the method is in our cache... this should just be a
91 // defered annotation!
92 map<const Method *, ExFunc>::iterator FI = Functions.find(M);
93 ExFunc Fn = (FI == Functions.end()) ? lookupMethod(M) : FI->second;
94 if (Fn == 0) {
95 cout << "Tried to execute an unknown external method: "
96 << M->getType()->getDescription() << " " << M->getName() << endl;
Chris Lattner4721f132001-10-30 20:28:00 +000097 return GenericValue();
Chris Lattner7720c8e2001-09-10 04:50:17 +000098 }
99
100 // TODO: FIXME when types are not const!
Chris Lattneref9c23f2001-10-03 14:53:21 +0000101 GenericValue Result = Fn(const_cast<MethodType*>(M->getMethodType()),ArgVals);
Chris Lattner4721f132001-10-30 20:28:00 +0000102 return Result;
Chris Lattner7720c8e2001-09-10 04:50:17 +0000103}
104
105
106//===----------------------------------------------------------------------===//
107// Methods "exported" to the running application...
108//
109extern "C" { // Don't add C++ manglings to llvm mangling :)
110
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000111// Implement void printstr([ubyte {x N}] *)
112GenericValue lle_VP_printstr(MethodType *M, const vector<GenericValue> &ArgVal){
113 assert(ArgVal.size() == 1 && "printstr only takes one argument!");
114 cout << (char*)ArgVal[0].PointerVal;
115 return GenericValue();
116}
117
Chris Lattner7720c8e2001-09-10 04:50:17 +0000118// Implement 'void print(X)' for every type...
119GenericValue lle_X_print(MethodType *M, const vector<GenericValue> &ArgVals) {
120 assert(ArgVals.size() == 1 && "generic print only takes one argument!");
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000121
122 Interpreter::print(M->getParamTypes()[0], ArgVals[0]);
123 return GenericValue();
124}
125
126// Implement 'void printVal(X)' for every type...
127GenericValue lle_X_printVal(MethodType *M, const vector<GenericValue> &ArgVal) {
128 assert(ArgVal.size() == 1 && "generic print only takes one argument!");
129
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000130 // Specialize print([ubyte {x N} ] *) and print(sbyte *)
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000131 if (PointerType *PTy = dyn_cast<PointerType>(M->getParamTypes()[0].get()))
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000132 if (PTy->getValueType() == Type::SByteTy ||
133 isa<ArrayType>(PTy->getValueType())) {
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000134 return lle_VP_printstr(M, ArgVal);
135 }
136
137 Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);
Chris Lattner7720c8e2001-09-10 04:50:17 +0000138 return GenericValue();
139}
140
Vikram S. Adve3eb60f82001-10-28 20:52:27 +0000141// Implement 'void printString(X)'
142// Argument must be [ubyte {x N} ] * or sbyte *
143GenericValue lle_X_printString(MethodType *M, const vector<GenericValue> &ArgVal) {
144 assert(ArgVal.size() == 1 && "generic print only takes one argument!");
145 return lle_VP_printstr(M, ArgVal);
146}
147
148// Implement 'void print<TYPE>(X)' for each primitive type or pointer type
149#define PRINT_TYPE_FUNC(TYPENAME,TYPEID) \
Chris Lattner316a65b2001-10-28 22:38:22 +0000150 GenericValue lle_X_print##TYPENAME(MethodType *M,\
151 const vector<GenericValue> &ArgVal) {\
Vikram S. Adve3eb60f82001-10-28 20:52:27 +0000152 assert(ArgVal.size() == 1 && "generic print only takes one argument!");\
Chris Lattner316a65b2001-10-28 22:38:22 +0000153 assert(M->getParamTypes()[0].get()->getPrimitiveID() == Type::##TYPEID);\
Vikram S. Adve3eb60f82001-10-28 20:52:27 +0000154 Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);\
155 return GenericValue();\
156 }
157
Chris Lattner4721f132001-10-30 20:28:00 +0000158PRINT_TYPE_FUNC(SByte, SByteTyID)
Vikram S. Adve3eb60f82001-10-28 20:52:27 +0000159PRINT_TYPE_FUNC(UByte, UByteTyID)
160PRINT_TYPE_FUNC(Short, ShortTyID)
161PRINT_TYPE_FUNC(UShort, UShortTyID)
162PRINT_TYPE_FUNC(Int, IntTyID)
163PRINT_TYPE_FUNC(UInt, UIntTyID)
164PRINT_TYPE_FUNC(Long, LongTyID)
165PRINT_TYPE_FUNC(ULong, ULongTyID)
166PRINT_TYPE_FUNC(Float, FloatTyID)
167PRINT_TYPE_FUNC(Double, DoubleTyID)
168PRINT_TYPE_FUNC(Pointer, PointerTyID)
169
170
Chris Lattner7720c8e2001-09-10 04:50:17 +0000171// void "putchar"(sbyte)
172GenericValue lle_Vb_putchar(MethodType *M, const vector<GenericValue> &Args) {
173 cout << Args[0].SByteVal;
174 return GenericValue();
175}
176
Chris Lattnere43db882001-10-27 04:15:57 +0000177// int "putchar"(int)
178GenericValue lle_ii_putchar(MethodType *M, const vector<GenericValue> &Args) {
179 cout << ((char)Args[0].IntVal) << flush;
180 return Args[0];
181}
182
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000183// void "putchar"(ubyte)
184GenericValue lle_VB_putchar(MethodType *M, const vector<GenericValue> &Args) {
Chris Lattnere43db882001-10-27 04:15:57 +0000185 cout << Args[0].SByteVal << flush;
186 return Args[0];
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000187}
188
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000189// void "__main"()
190GenericValue lle_V___main(MethodType *M, const vector<GenericValue> &Args) {
191 return GenericValue();
192}
193
Chris Lattnere43db882001-10-27 04:15:57 +0000194// void "exit"(int)
195GenericValue lle_Vi_exit(MethodType *M, const vector<GenericValue> &Args) {
196 TheInterpreter->exitCalled(Args[0]);
197 return GenericValue();
198}
199
Chris Lattnerc2593162001-10-27 08:28:11 +0000200// void *malloc(uint)
201GenericValue lle_PI_malloc(MethodType *M, const vector<GenericValue> &Args) {
Chris Lattner4721f132001-10-30 20:28:00 +0000202 assert(Args.size() == 1 && "Malloc expects one argument!");
Chris Lattnerc2593162001-10-27 08:28:11 +0000203 GenericValue GV;
Chris Lattner4721f132001-10-30 20:28:00 +0000204 GV.PointerVal = (uint64_t)malloc(Args[0].UIntVal);
Chris Lattnerc2593162001-10-27 08:28:11 +0000205 return GV;
206}
207
208// void free(void *)
209GenericValue lle_VP_free(MethodType *M, const vector<GenericValue> &Args) {
Chris Lattner4721f132001-10-30 20:28:00 +0000210 free((void*)Args[0].PointerVal);
Chris Lattnerc2593162001-10-27 08:28:11 +0000211 return GenericValue();
212}
213
214// double pow(double, double)
215GenericValue lle_DDD_pow(MethodType *M, const vector<GenericValue> &Args) {
216 GenericValue GV;
Chris Lattner08845a22001-10-29 20:27:45 +0000217 GV.DoubleVal = pow(Args[0].DoubleVal, Args[1].DoubleVal);
Chris Lattnerc2593162001-10-27 08:28:11 +0000218 return GV;
219}
220
221
Chris Lattner08845a22001-10-29 20:27:45 +0000222// int printf(sbyte *, ...) - a very rough implementation to make output useful.
223GenericValue lle_iP_printf(MethodType *M, const vector<GenericValue> &Args) {
224 const char *FmtStr = (const char *)Args[0].PointerVal;
225 unsigned ArgNo = 1;
226
227 // printf should return # chars printed. This is completely incorrect, but
228 // close enough for now.
229 GenericValue GV; GV.IntVal = strlen(FmtStr);
230 while (1) {
231 switch (*FmtStr) {
232 case 0: return GV; // Null terminator...
233 default: // Normal nonspecial character
234 cout << *FmtStr++;
235 break;
236 case '\\': { // Handle escape codes
237 char Buffer[3];
238 Buffer[0] = *FmtStr++;
239 Buffer[1] = *FmtStr++;
240 Buffer[2] = 0;
241 cout << Buffer;
242 break;
243 }
244 case '%': { // Handle format specifiers
245 bool isLong = false;
246 ++FmtStr;
247 if (*FmtStr == 'l') {
248 isLong = true;
249 FmtStr++;
250 }
251
252 switch (*FmtStr) {
253 case '%': cout << *FmtStr; break; // %%
254 case 'd': // %d %i
255 case 'i': cout << Args[ArgNo++].IntVal; break;
256 case 'u': cout << Args[ArgNo++].UIntVal; break; // %u
257 case 'o': cout << oct << Args[ArgNo++].UIntVal << dec; break; // %o
258 case 'x':
259 case 'X': cout << hex << Args[ArgNo++].UIntVal << dec; break; // %x %X
260 case 'e': case 'E': case 'g': case 'G': // %[eEgG]
261 cout /*<< std::scientific*/ << Args[ArgNo++].DoubleVal
262 /*<< std::fixed*/; break;
263 case 'f': cout << Args[ArgNo++].DoubleVal; break; // %f
264 case 'c': cout << Args[ArgNo++].UByteVal; break; // %c
265 case 's': cout << (char*)Args[ArgNo++].PointerVal; break; // %s
266 default: cout << "<unknown printf code '" << *FmtStr << "'!>";
267 ArgNo++; break;
268 }
269 ++FmtStr;
270 break;
271 }
272 }
273 }
274}
275
Chris Lattner7720c8e2001-09-10 04:50:17 +0000276} // End extern "C"
Chris Lattner4721f132001-10-30 20:28:00 +0000277
278
279void Interpreter::initializeExternalMethods() {
280 FuncNames["lle_VP_printstr"] = lle_VP_printstr;
281 FuncNames["lle_X_print"] = lle_X_print;
282 FuncNames["lle_X_printVal"] = lle_X_printVal;
283 FuncNames["lle_X_printString"] = lle_X_printString;
284 FuncNames["lle_X_printUByte"] = lle_X_printUByte;
285 FuncNames["lle_X_printSByte"] = lle_X_printSByte;
286 FuncNames["lle_X_printUShort"] = lle_X_printUShort;
287 FuncNames["lle_X_printShort"] = lle_X_printShort;
288 FuncNames["lle_X_printInt"] = lle_X_printInt;
289 FuncNames["lle_X_printUInt"] = lle_X_printUInt;
290 FuncNames["lle_X_printLong"] = lle_X_printLong;
291 FuncNames["lle_X_printULong"] = lle_X_printULong;
292 FuncNames["lle_X_printFloat"] = lle_X_printFloat;
293 FuncNames["lle_X_printDouble"] = lle_X_printDouble;
294 FuncNames["lle_X_printPointer"] = lle_X_printPointer;
295 FuncNames["lle_Vb_putchar"] = lle_Vb_putchar;
296 FuncNames["lle_ii_putchar"] = lle_ii_putchar;
297 FuncNames["lle_VB_putchar"] = lle_VB_putchar;
298 FuncNames["lle_V___main"] = lle_V___main;
299 FuncNames["lle_Vi_exit"] = lle_Vi_exit;
300 FuncNames["lle_PI_malloc"] = lle_PI_malloc;
301 FuncNames["lle_VP_free"] = lle_VP_free;
302 FuncNames["lle_DDD_pow"] = lle_DDD_pow;
303 FuncNames["lle_iP_printf"] = lle_iP_printf;
304}