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 = (uint64_t)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();
216 // double pow(double, double)
217 GenericValue lle_X_pow(MethodType *M, const vector<GenericValue> &Args) {
218 assert(Args.size() == 2);
220 GV.DoubleVal = pow(Args[0].DoubleVal, Args[1].DoubleVal);
224 // double sqrt(double)
225 GenericValue lle_X_sqrt(MethodType *M, const vector<GenericValue> &Args) {
226 assert(Args.size() == 1);
228 GV.DoubleVal = sqrt(Args[0].DoubleVal);
232 // double log(double)
233 GenericValue lle_X_log(MethodType *M, const vector<GenericValue> &Args) {
234 assert(Args.size() == 1);
236 GV.DoubleVal = log(Args[0].DoubleVal);
241 GenericValue lle_X_drand48(MethodType *M, const vector<GenericValue> &Args) {
242 assert(Args.size() == 0);
244 GV.DoubleVal = drand48();
249 // int printf(sbyte *, ...) - a very rough implementation to make output useful.
250 GenericValue lle_X_printf(MethodType *M, const vector<GenericValue> &Args) {
251 const char *FmtStr = (const char *)Args[0].PointerVal;
254 // printf should return # chars printed. This is completely incorrect, but
255 // close enough for now.
256 GenericValue GV; GV.IntVal = strlen(FmtStr);
259 case 0: return GV; // Null terminator...
260 default: // Normal nonspecial character
263 case '\\': { // Handle escape codes
265 Buffer[0] = *FmtStr++;
266 Buffer[1] = *FmtStr++;
271 case '%': { // Handle format specifiers
274 if (*FmtStr == 'l') {
280 cout << *FmtStr; // %%
282 char Fmt[] = "%d", Buffer[1000] = "";
287 sprintf(Buffer, Fmt, Args[ArgNo++].SByteVal); break;
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 << "'!>";
310 void 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;
326 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;
334 FuncNames["lle_X_sqrt"] = lle_X_sqrt;
335 FuncNames["lle_X_printf"] = lle_X_printf;