blob: 7c60126aaefcc91f129e20f929cd3f68e0fa4c62 [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;
21
Chris Lattnere43db882001-10-27 04:15:57 +000022static Interpreter *TheInterpreter;
23
24// getCurrentExecutablePath() - Return the directory that the lli executable
25// lives in.
26//
27string Interpreter::getCurrentExecutablePath() const {
28 Dl_info Info;
29 if (dladdr(&TheInterpreter, &Info) == 0) return "";
30
31 string LinkAddr(Info.dli_fname);
32 unsigned SlashPos = LinkAddr.rfind('/');
33 if (SlashPos != string::npos)
34 LinkAddr.resize(SlashPos); // Trim the executable name off...
35
36 return LinkAddr;
37}
38
39
Chris Lattner7720c8e2001-09-10 04:50:17 +000040static char getTypeID(const Type *Ty) {
41 switch (Ty->getPrimitiveID()) {
42 case Type::VoidTyID: return 'V';
43 case Type::BoolTyID: return 'o';
44 case Type::UByteTyID: return 'B';
45 case Type::SByteTyID: return 'b';
46 case Type::UShortTyID: return 'S';
47 case Type::ShortTyID: return 's';
48 case Type::UIntTyID: return 'I';
49 case Type::IntTyID: return 'i';
50 case Type::ULongTyID: return 'L';
51 case Type::LongTyID: return 'l';
52 case Type::FloatTyID: return 'F';
53 case Type::DoubleTyID: return 'D';
54 case Type::PointerTyID: return 'P';
55 case Type::MethodTyID: return 'M';
56 case Type::StructTyID: return 'T';
57 case Type::ArrayTyID: return 'A';
58 case Type::OpaqueTyID: return 'O';
59 default: return 'U';
60 }
61}
62
63static ExFunc lookupMethod(const Method *M) {
64 // Function not found, look it up... start by figuring out what the
65 // composite function name should be.
66 string ExtName = "lle_";
Chris Lattneref9c23f2001-10-03 14:53:21 +000067 const MethodType *MT = M->getMethodType();
Chris Lattner7720c8e2001-09-10 04:50:17 +000068 for (unsigned i = 0; const Type *Ty = MT->getContainedType(i); ++i)
69 ExtName += getTypeID(Ty);
70 ExtName += "_" + M->getName();
71
72 //cout << "Tried: '" << ExtName << "'\n";
73 ExFunc FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ExtName.c_str());
74 if (FnPtr == 0) // Try calling a generic function... if it exists...
75 FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ("lle_X_"+M->getName()).c_str());
76 if (FnPtr != 0)
77 Functions.insert(make_pair(M, FnPtr)); // Cache for later
78 return FnPtr;
79}
80
81void Interpreter::callExternalMethod(Method *M,
82 const vector<GenericValue> &ArgVals) {
Chris Lattnere43db882001-10-27 04:15:57 +000083 TheInterpreter = this;
84
Chris Lattner7720c8e2001-09-10 04:50:17 +000085 // Do a lookup to see if the method is in our cache... this should just be a
86 // defered annotation!
87 map<const Method *, ExFunc>::iterator FI = Functions.find(M);
88 ExFunc Fn = (FI == Functions.end()) ? lookupMethod(M) : FI->second;
89 if (Fn == 0) {
90 cout << "Tried to execute an unknown external method: "
91 << M->getType()->getDescription() << " " << M->getName() << endl;
92 return;
93 }
94
95 // TODO: FIXME when types are not const!
Chris Lattneref9c23f2001-10-03 14:53:21 +000096 GenericValue Result = Fn(const_cast<MethodType*>(M->getMethodType()),ArgVals);
Chris Lattner7720c8e2001-09-10 04:50:17 +000097
98 // Copy the result back into the result variable if we are not returning void.
99 if (M->getReturnType() != Type::VoidTy) {
100 CallInst *Caller = ECStack.back().Caller;
101 if (Caller) {
102
103 } else {
104 // print it.
105 }
106 }
107}
108
109
110//===----------------------------------------------------------------------===//
111// Methods "exported" to the running application...
112//
113extern "C" { // Don't add C++ manglings to llvm mangling :)
114
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000115// Implement void printstr([ubyte {x N}] *)
116GenericValue lle_VP_printstr(MethodType *M, const vector<GenericValue> &ArgVal){
117 assert(ArgVal.size() == 1 && "printstr only takes one argument!");
118 cout << (char*)ArgVal[0].PointerVal;
119 return GenericValue();
120}
121
Chris Lattner7720c8e2001-09-10 04:50:17 +0000122// Implement 'void print(X)' for every type...
123GenericValue lle_X_print(MethodType *M, const vector<GenericValue> &ArgVals) {
124 assert(ArgVals.size() == 1 && "generic print only takes one argument!");
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000125
126 Interpreter::print(M->getParamTypes()[0], ArgVals[0]);
127 return GenericValue();
128}
129
130// Implement 'void printVal(X)' for every type...
131GenericValue lle_X_printVal(MethodType *M, const vector<GenericValue> &ArgVal) {
132 assert(ArgVal.size() == 1 && "generic print only takes one argument!");
133
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000134 // Specialize print([ubyte {x N} ] *) and print(sbyte *)
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000135 if (PointerType *PTy = dyn_cast<PointerType>(M->getParamTypes()[0].get()))
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000136 if (PTy->getValueType() == Type::SByteTy ||
137 isa<ArrayType>(PTy->getValueType())) {
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000138 return lle_VP_printstr(M, ArgVal);
139 }
140
141 Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);
Chris Lattner7720c8e2001-09-10 04:50:17 +0000142 return GenericValue();
143}
144
Vikram S. Adve3eb60f82001-10-28 20:52:27 +0000145// Implement 'void printString(X)'
146// Argument must be [ubyte {x N} ] * or sbyte *
147GenericValue lle_X_printString(MethodType *M, const vector<GenericValue> &ArgVal) {
148 assert(ArgVal.size() == 1 && "generic print only takes one argument!");
149 return lle_VP_printstr(M, ArgVal);
150}
151
152// Implement 'void print<TYPE>(X)' for each primitive type or pointer type
153#define PRINT_TYPE_FUNC(TYPENAME,TYPEID) \
154 GenericValue lle_X_print##TYPENAME##(MethodType *M,\
155 const vector<GenericValue> &ArgVal) {\
156 assert(ArgVal.size() == 1 && "generic print only takes one argument!");\
157 assert(M->getParamTypes()[0].get()->getPrimitiveID()\
158 == Type::##TYPEID##);\
159 Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);\
160 return GenericValue();\
161 }
162
163PRINT_TYPE_FUNC(Byte, SByteTyID)
164PRINT_TYPE_FUNC(UByte, UByteTyID)
165PRINT_TYPE_FUNC(Short, ShortTyID)
166PRINT_TYPE_FUNC(UShort, UShortTyID)
167PRINT_TYPE_FUNC(Int, IntTyID)
168PRINT_TYPE_FUNC(UInt, UIntTyID)
169PRINT_TYPE_FUNC(Long, LongTyID)
170PRINT_TYPE_FUNC(ULong, ULongTyID)
171PRINT_TYPE_FUNC(Float, FloatTyID)
172PRINT_TYPE_FUNC(Double, DoubleTyID)
173PRINT_TYPE_FUNC(Pointer, PointerTyID)
174
175
Chris Lattner7720c8e2001-09-10 04:50:17 +0000176// void "putchar"(sbyte)
177GenericValue lle_Vb_putchar(MethodType *M, const vector<GenericValue> &Args) {
178 cout << Args[0].SByteVal;
179 return GenericValue();
180}
181
Chris Lattnere43db882001-10-27 04:15:57 +0000182// int "putchar"(int)
183GenericValue lle_ii_putchar(MethodType *M, const vector<GenericValue> &Args) {
184 cout << ((char)Args[0].IntVal) << flush;
185 return Args[0];
186}
187
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000188// void "putchar"(ubyte)
189GenericValue lle_VB_putchar(MethodType *M, const vector<GenericValue> &Args) {
Chris Lattnere43db882001-10-27 04:15:57 +0000190 cout << Args[0].SByteVal << flush;
191 return Args[0];
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000192}
193
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000194// void "__main"()
195GenericValue lle_V___main(MethodType *M, const vector<GenericValue> &Args) {
196 return GenericValue();
197}
198
Chris Lattnere43db882001-10-27 04:15:57 +0000199// void "exit"(int)
200GenericValue lle_Vi_exit(MethodType *M, const vector<GenericValue> &Args) {
201 TheInterpreter->exitCalled(Args[0]);
202 return GenericValue();
203}
204
Chris Lattnerc2593162001-10-27 08:28:11 +0000205// void *malloc(uint)
206GenericValue lle_PI_malloc(MethodType *M, const vector<GenericValue> &Args) {
207 GenericValue GV;
208 GV.LongVal = (uint64_t)malloc(Args[0].UIntVal);
209 return GV;
210}
211
212// void free(void *)
213GenericValue lle_VP_free(MethodType *M, const vector<GenericValue> &Args) {
214 free((void*)Args[0].LongVal);
215 return GenericValue();
216}
217
218// double pow(double, double)
219GenericValue lle_DDD_pow(MethodType *M, const vector<GenericValue> &Args) {
220 GenericValue GV;
221 GV.DoubleVal = pow(GV.DoubleVal, GV.DoubleVal);
222 return GV;
223}
224
225
Chris Lattner7720c8e2001-09-10 04:50:17 +0000226} // End extern "C"