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"
19 typedef GenericValue (*ExFunc)(MethodType *, const vector<GenericValue> &);
20 static map<const Method *, ExFunc> Functions;
21 static map<string, ExFunc> FuncNames;
23 static Interpreter *TheInterpreter;
25 // getCurrentExecutablePath() - Return the directory that the lli executable
28 string Interpreter::getCurrentExecutablePath() const {
30 if (dladdr(&TheInterpreter, &Info) == 0) return "";
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...
41 static 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';
64 static 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_";
68 const MethodType *MT = M->getMethodType();
69 for (unsigned i = 0; const Type *Ty = MT->getContainedType(i); ++i)
70 ExtName += getTypeID(Ty);
71 ExtName += "_" + M->getName();
73 //cout << "Tried: '" << ExtName << "'\n";
74 ExFunc FnPtr = FuncNames[ExtName];
76 FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ExtName.c_str());
78 FnPtr = FuncNames["lle_X_"+M->getName()];
79 if (FnPtr == 0) // Try calling a generic function... if it exists...
80 FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ("lle_X_"+M->getName()).c_str());
82 Functions.insert(make_pair(M, FnPtr)); // Cache for later
86 GenericValue Interpreter::callExternalMethod(Method *M,
87 const vector<GenericValue> &ArgVals) {
88 TheInterpreter = this;
90 // 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;
95 cout << "Tried to execute an unknown external method: "
96 << M->getType()->getDescription() << " " << M->getName() << endl;
97 return GenericValue();
100 // TODO: FIXME when types are not const!
101 GenericValue Result = Fn(const_cast<MethodType*>(M->getMethodType()),ArgVals);
106 //===----------------------------------------------------------------------===//
107 // Methods "exported" to the running application...
109 extern "C" { // Don't add C++ manglings to llvm mangling :)
111 // Implement void printstr([ubyte {x N}] *)
112 GenericValue 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();
118 // Implement 'void print(X)' for every type...
119 GenericValue lle_X_print(MethodType *M, const vector<GenericValue> &ArgVals) {
120 assert(ArgVals.size() == 1 && "generic print only takes one argument!");
122 Interpreter::print(M->getParamTypes()[0], ArgVals[0]);
123 return GenericValue();
126 // Implement 'void printVal(X)' for every type...
127 GenericValue lle_X_printVal(MethodType *M, const vector<GenericValue> &ArgVal) {
128 assert(ArgVal.size() == 1 && "generic print only takes one argument!");
130 // Specialize print([ubyte {x N} ] *) and print(sbyte *)
131 if (PointerType *PTy = dyn_cast<PointerType>(M->getParamTypes()[0].get()))
132 if (PTy->getValueType() == Type::SByteTy ||
133 isa<ArrayType>(PTy->getValueType())) {
134 return lle_VP_printstr(M, ArgVal);
137 Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);
138 return GenericValue();
141 // Implement 'void printString(X)'
142 // Argument must be [ubyte {x N} ] * or sbyte *
143 GenericValue 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);
148 // Implement 'void print<TYPE>(X)' for each primitive type or pointer type
149 #define PRINT_TYPE_FUNC(TYPENAME,TYPEID) \
150 GenericValue lle_X_print##TYPENAME(MethodType *M,\
151 const vector<GenericValue> &ArgVal) {\
152 assert(ArgVal.size() == 1 && "generic print only takes one argument!");\
153 assert(M->getParamTypes()[0].get()->getPrimitiveID() == Type::##TYPEID);\
154 Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);\
155 return GenericValue();\
158 PRINT_TYPE_FUNC(SByte, SByteTyID)
159 PRINT_TYPE_FUNC(UByte, UByteTyID)
160 PRINT_TYPE_FUNC(Short, ShortTyID)
161 PRINT_TYPE_FUNC(UShort, UShortTyID)
162 PRINT_TYPE_FUNC(Int, IntTyID)
163 PRINT_TYPE_FUNC(UInt, UIntTyID)
164 PRINT_TYPE_FUNC(Long, LongTyID)
165 PRINT_TYPE_FUNC(ULong, ULongTyID)
166 PRINT_TYPE_FUNC(Float, FloatTyID)
167 PRINT_TYPE_FUNC(Double, DoubleTyID)
168 PRINT_TYPE_FUNC(Pointer, PointerTyID)
171 // void "putchar"(sbyte)
172 GenericValue lle_Vb_putchar(MethodType *M, const vector<GenericValue> &Args) {
173 cout << Args[0].SByteVal;
174 return GenericValue();
177 // int "putchar"(int)
178 GenericValue lle_ii_putchar(MethodType *M, const vector<GenericValue> &Args) {
179 cout << ((char)Args[0].IntVal) << flush;
183 // void "putchar"(ubyte)
184 GenericValue lle_VB_putchar(MethodType *M, const vector<GenericValue> &Args) {
185 cout << Args[0].SByteVal << flush;
190 GenericValue lle_V___main(MethodType *M, const vector<GenericValue> &Args) {
191 return GenericValue();
195 GenericValue lle_X_exit(MethodType *M, const vector<GenericValue> &Args) {
196 TheInterpreter->exitCalled(Args[0]);
197 return GenericValue();
200 // void *malloc(uint)
201 GenericValue lle_X_malloc(MethodType *M, const vector<GenericValue> &Args) {
202 assert(Args.size() == 1 && "Malloc expects one argument!");
204 GV.PointerVal = (uint64_t)malloc(Args[0].UIntVal);
209 GenericValue lle_X_free(MethodType *M, const vector<GenericValue> &Args) {
210 free((void*)Args[0].PointerVal);
211 return GenericValue();
214 // double pow(double, double)
215 GenericValue lle_X_pow(MethodType *M, const vector<GenericValue> &Args) {
217 GV.DoubleVal = pow(Args[0].DoubleVal, Args[1].DoubleVal);
222 // int printf(sbyte *, ...) - a very rough implementation to make output useful.
223 GenericValue lle_X_printf(MethodType *M, const vector<GenericValue> &Args) {
224 const char *FmtStr = (const char *)Args[0].PointerVal;
227 // printf should return # chars printed. This is completely incorrect, but
228 // close enough for now.
229 GenericValue GV; GV.IntVal = strlen(FmtStr);
232 case 0: return GV; // Null terminator...
233 default: // Normal nonspecial character
236 case '\\': { // Handle escape codes
238 Buffer[0] = *FmtStr++;
239 Buffer[1] = *FmtStr++;
244 case '%': { // Handle format specifiers
247 if (*FmtStr == 'l') {
253 case '%': cout << *FmtStr; break; // %%
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
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 << "'!>";
279 void 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_X_exit"] = lle_X_exit;
300 FuncNames["lle_X_malloc"] = lle_X_malloc;
301 FuncNames["lle_X_free"] = lle_X_free;
302 FuncNames["lle_X_pow"] = lle_X_pow;
303 FuncNames["lle_X_printf"] = lle_X_printf;