blob: 82da428f88f2e62333c1c839076af6c1b9008025 [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) \
Chris Lattner316a65b2001-10-28 22:38:22 +0000154 GenericValue lle_X_print##TYPENAME(MethodType *M,\
155 const vector<GenericValue> &ArgVal) {\
Vikram S. Adve3eb60f82001-10-28 20:52:27 +0000156 assert(ArgVal.size() == 1 && "generic print only takes one argument!");\
Chris Lattner316a65b2001-10-28 22:38:22 +0000157 assert(M->getParamTypes()[0].get()->getPrimitiveID() == Type::##TYPEID);\
Vikram S. Adve3eb60f82001-10-28 20:52:27 +0000158 Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);\
159 return GenericValue();\
160 }
161
162PRINT_TYPE_FUNC(Byte, SByteTyID)
163PRINT_TYPE_FUNC(UByte, UByteTyID)
164PRINT_TYPE_FUNC(Short, ShortTyID)
165PRINT_TYPE_FUNC(UShort, UShortTyID)
166PRINT_TYPE_FUNC(Int, IntTyID)
167PRINT_TYPE_FUNC(UInt, UIntTyID)
168PRINT_TYPE_FUNC(Long, LongTyID)
169PRINT_TYPE_FUNC(ULong, ULongTyID)
170PRINT_TYPE_FUNC(Float, FloatTyID)
171PRINT_TYPE_FUNC(Double, DoubleTyID)
172PRINT_TYPE_FUNC(Pointer, PointerTyID)
173
174
Chris Lattner7720c8e2001-09-10 04:50:17 +0000175// void "putchar"(sbyte)
176GenericValue lle_Vb_putchar(MethodType *M, const vector<GenericValue> &Args) {
177 cout << Args[0].SByteVal;
178 return GenericValue();
179}
180
Chris Lattnere43db882001-10-27 04:15:57 +0000181// int "putchar"(int)
182GenericValue lle_ii_putchar(MethodType *M, const vector<GenericValue> &Args) {
183 cout << ((char)Args[0].IntVal) << flush;
184 return Args[0];
185}
186
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000187// void "putchar"(ubyte)
188GenericValue lle_VB_putchar(MethodType *M, const vector<GenericValue> &Args) {
Chris Lattnere43db882001-10-27 04:15:57 +0000189 cout << Args[0].SByteVal << flush;
190 return Args[0];
Chris Lattner2e42d3a2001-10-15 05:51:48 +0000191}
192
Chris Lattnerf8f2afb2001-10-18 21:55:32 +0000193// void "__main"()
194GenericValue lle_V___main(MethodType *M, const vector<GenericValue> &Args) {
195 return GenericValue();
196}
197
Chris Lattnere43db882001-10-27 04:15:57 +0000198// void "exit"(int)
199GenericValue lle_Vi_exit(MethodType *M, const vector<GenericValue> &Args) {
200 TheInterpreter->exitCalled(Args[0]);
201 return GenericValue();
202}
203
Chris Lattnerc2593162001-10-27 08:28:11 +0000204// void *malloc(uint)
205GenericValue lle_PI_malloc(MethodType *M, const vector<GenericValue> &Args) {
206 GenericValue GV;
207 GV.LongVal = (uint64_t)malloc(Args[0].UIntVal);
208 return GV;
209}
210
211// void free(void *)
212GenericValue lle_VP_free(MethodType *M, const vector<GenericValue> &Args) {
213 free((void*)Args[0].LongVal);
214 return GenericValue();
215}
216
217// double pow(double, double)
218GenericValue lle_DDD_pow(MethodType *M, const vector<GenericValue> &Args) {
219 GenericValue GV;
220 GV.DoubleVal = pow(GV.DoubleVal, GV.DoubleVal);
221 return GV;
222}
223
224
Chris Lattner7720c8e2001-09-10 04:50:17 +0000225} // End extern "C"