blob: 14dcdf9e0364595cab0c8d5d60dbcdf3a8a69b6e [file] [log] [blame]
Dan Gohmanf17a25c2007-07-18 16:29:46 +00001//===-- ExternalFunctions.cpp - Implement External Functions --------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains both code to deal with invoking "external" functions, but
11// also contains code that implements "exported" external functions.
12//
13// External functions in the interpreter are implemented by
14// using the system's dynamic loader to look up the address of the function
15// we want to invoke. If a function is found, then one of the
16// many lle_* wrapper functions in this file will translate its arguments from
17// GenericValues to the types the function is actually expecting, before the
18// function is called.
19//
20//===----------------------------------------------------------------------===//
21
22#include "Interpreter.h"
23#include "llvm/DerivedTypes.h"
24#include "llvm/Module.h"
25#include "llvm/Support/Streams.h"
26#include "llvm/System/DynamicLibrary.h"
27#include "llvm/Target/TargetData.h"
28#include <csignal>
29#include <map>
30#include <cmath>
31using std::vector;
32
33using namespace llvm;
34
35typedef GenericValue (*ExFunc)(FunctionType *, const vector<GenericValue> &);
36static std::map<const Function *, ExFunc> Functions;
37static std::map<std::string, ExFunc> FuncNames;
38
39static Interpreter *TheInterpreter;
40
41static char getTypeID(const Type *Ty) {
42 switch (Ty->getTypeID()) {
43 case Type::VoidTyID: return 'V';
44 case Type::IntegerTyID:
45 switch (cast<IntegerType>(Ty)->getBitWidth()) {
46 case 1: return 'o';
47 case 8: return 'B';
48 case 16: return 'S';
49 case 32: return 'I';
50 case 64: return 'L';
51 default: return 'N';
52 }
53 case Type::FloatTyID: return 'F';
54 case Type::DoubleTyID: return 'D';
55 case Type::PointerTyID: return 'P';
56 case Type::FunctionTyID: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 lookupFunction(const Function *F) {
65 // Function not found, look it up... start by figuring out what the
66 // composite function name should be.
67 std::string ExtName = "lle_";
68 const FunctionType *FT = F->getFunctionType();
69 for (unsigned i = 0, e = FT->getNumContainedTypes(); i != e; ++i)
70 ExtName += getTypeID(FT->getContainedType(i));
71 ExtName += "_" + F->getName();
72
73 ExFunc FnPtr = FuncNames[ExtName];
74 if (FnPtr == 0)
75 FnPtr = FuncNames["lle_X_"+F->getName()];
76 if (FnPtr == 0) // Try calling a generic function... if it exists...
77 FnPtr = (ExFunc)(intptr_t)sys::DynamicLibrary::SearchForAddressOfSymbol(
78 ("lle_X_"+F->getName()).c_str());
79 if (FnPtr == 0)
80 FnPtr = (ExFunc)(intptr_t)
81 sys::DynamicLibrary::SearchForAddressOfSymbol(F->getName());
82 if (FnPtr != 0)
83 Functions.insert(std::make_pair(F, FnPtr)); // Cache for later
84 return FnPtr;
85}
86
87GenericValue Interpreter::callExternalFunction(Function *F,
88 const std::vector<GenericValue> &ArgVals) {
89 TheInterpreter = this;
90
91 // Do a lookup to see if the function is in our cache... this should just be a
92 // deferred annotation!
93 std::map<const Function *, ExFunc>::iterator FI = Functions.find(F);
94 ExFunc Fn = (FI == Functions.end()) ? lookupFunction(F) : FI->second;
95 if (Fn == 0) {
96 cerr << "Tried to execute an unknown external function: "
97 << F->getType()->getDescription() << " " << F->getName() << "\n";
98 if (F->getName() == "__main")
99 return GenericValue();
100 abort();
101 }
102
103 // TODO: FIXME when types are not const!
104 GenericValue Result = Fn(const_cast<FunctionType*>(F->getFunctionType()),
105 ArgVals);
106 return Result;
107}
108
109
110//===----------------------------------------------------------------------===//
111// Functions "exported" to the running application...
112//
113extern "C" { // Don't add C++ manglings to llvm mangling :)
114
115// void putchar(ubyte)
116GenericValue lle_X_putchar(FunctionType *FT, const vector<GenericValue> &Args){
117 cout << ((char)Args[0].IntVal.getZExtValue()) << std::flush;
118 return Args[0];
119}
120
121// void _IO_putc(int c, FILE* fp)
122GenericValue lle_X__IO_putc(FunctionType *FT, const vector<GenericValue> &Args){
123#ifdef __linux__
124 _IO_putc((char)Args[0].IntVal.getZExtValue(), (FILE*) Args[1].PointerVal);
125#else
126 assert(0 && "Can't call _IO_putc on this platform");
127#endif
128 return Args[0];
129}
130
131// void atexit(Function*)
132GenericValue lle_X_atexit(FunctionType *FT, const vector<GenericValue> &Args) {
133 assert(Args.size() == 1);
134 TheInterpreter->addAtExitHandler((Function*)GVTOP(Args[0]));
135 GenericValue GV;
136 GV.IntVal = 0;
137 return GV;
138}
139
140// void exit(int)
141GenericValue lle_X_exit(FunctionType *FT, const vector<GenericValue> &Args) {
142 TheInterpreter->exitCalled(Args[0]);
143 return GenericValue();
144}
145
146// void abort(void)
147GenericValue lle_X_abort(FunctionType *FT, const vector<GenericValue> &Args) {
148 raise (SIGABRT);
149 return GenericValue();
150}
151
152// void *malloc(uint)
153GenericValue lle_X_malloc(FunctionType *FT, const vector<GenericValue> &Args) {
154 assert(Args.size() == 1 && "Malloc expects one argument!");
155 assert(isa<PointerType>(FT->getReturnType()) && "malloc must return pointer");
156 return PTOGV(malloc(Args[0].IntVal.getZExtValue()));
157}
158
159// void *calloc(uint, uint)
160GenericValue lle_X_calloc(FunctionType *FT, const vector<GenericValue> &Args) {
161 assert(Args.size() == 2 && "calloc expects two arguments!");
162 assert(isa<PointerType>(FT->getReturnType()) && "calloc must return pointer");
163 return PTOGV(calloc(Args[0].IntVal.getZExtValue(),
164 Args[1].IntVal.getZExtValue()));
165}
166
167// void *calloc(uint, uint)
168GenericValue lle_X_realloc(FunctionType *FT, const vector<GenericValue> &Args) {
169 assert(Args.size() == 2 && "calloc expects two arguments!");
170 assert(isa<PointerType>(FT->getReturnType()) &&"realloc must return pointer");
171 return PTOGV(realloc(GVTOP(Args[0]), Args[1].IntVal.getZExtValue()));
172}
173
174// void free(void *)
175GenericValue lle_X_free(FunctionType *FT, const vector<GenericValue> &Args) {
176 assert(Args.size() == 1);
177 free(GVTOP(Args[0]));
178 return GenericValue();
179}
180
181// int atoi(char *)
182GenericValue lle_X_atoi(FunctionType *FT, const vector<GenericValue> &Args) {
183 assert(Args.size() == 1);
184 GenericValue GV;
185 GV.IntVal = APInt(32, atoi((char*)GVTOP(Args[0])));
186 return GV;
187}
188
189// double pow(double, double)
190GenericValue lle_X_pow(FunctionType *FT, const vector<GenericValue> &Args) {
191 assert(Args.size() == 2);
192 GenericValue GV;
193 GV.DoubleVal = pow(Args[0].DoubleVal, Args[1].DoubleVal);
194 return GV;
195}
196
197// double exp(double)
198GenericValue lle_X_exp(FunctionType *FT, const vector<GenericValue> &Args) {
199 assert(Args.size() == 1);
200 GenericValue GV;
201 GV.DoubleVal = exp(Args[0].DoubleVal);
202 return GV;
203}
204
205// double sqrt(double)
206GenericValue lle_X_sqrt(FunctionType *FT, const vector<GenericValue> &Args) {
207 assert(Args.size() == 1);
208 GenericValue GV;
209 GV.DoubleVal = sqrt(Args[0].DoubleVal);
210 return GV;
211}
212
213// double log(double)
214GenericValue lle_X_log(FunctionType *FT, const vector<GenericValue> &Args) {
215 assert(Args.size() == 1);
216 GenericValue GV;
217 GV.DoubleVal = log(Args[0].DoubleVal);
218 return GV;
219}
220
221// double floor(double)
222GenericValue lle_X_floor(FunctionType *FT, const vector<GenericValue> &Args) {
223 assert(Args.size() == 1);
224 GenericValue GV;
225 GV.DoubleVal = floor(Args[0].DoubleVal);
226 return GV;
227}
228
229#ifdef HAVE_RAND48
230
231// double drand48()
232GenericValue lle_X_drand48(FunctionType *FT, const vector<GenericValue> &Args) {
233 assert(Args.size() == 0);
234 GenericValue GV;
235 GV.DoubleVal = drand48();
236 return GV;
237}
238
239// long lrand48()
240GenericValue lle_X_lrand48(FunctionType *FT, const vector<GenericValue> &Args) {
241 assert(Args.size() == 0);
242 GenericValue GV;
243 GV.Int32Val = lrand48();
244 return GV;
245}
246
247// void srand48(long)
248GenericValue lle_X_srand48(FunctionType *FT, const vector<GenericValue> &Args) {
249 assert(Args.size() == 1);
250 srand48(Args[0].Int32Val);
251 return GenericValue();
252}
253
254#endif
255
256// int rand()
257GenericValue lle_X_rand(FunctionType *FT, const vector<GenericValue> &Args) {
258 assert(Args.size() == 0);
259 GenericValue GV;
260 GV.IntVal = APInt(32, rand());
261 return GV;
262}
263
264// void srand(uint)
265GenericValue lle_X_srand(FunctionType *FT, const vector<GenericValue> &Args) {
266 assert(Args.size() == 1);
267 srand(Args[0].IntVal.getZExtValue());
268 return GenericValue();
269}
270
271// int puts(const char*)
272GenericValue lle_X_puts(FunctionType *FT, const vector<GenericValue> &Args) {
273 assert(Args.size() == 1);
274 GenericValue GV;
275 GV.IntVal = APInt(32, puts((char*)GVTOP(Args[0])));
276 return GV;
277}
278
279// int sprintf(sbyte *, sbyte *, ...) - a very rough implementation to make
280// output useful.
281GenericValue lle_X_sprintf(FunctionType *FT, const vector<GenericValue> &Args) {
282 char *OutputBuffer = (char *)GVTOP(Args[0]);
283 const char *FmtStr = (const char *)GVTOP(Args[1]);
284 unsigned ArgNo = 2;
285
286 // printf should return # chars printed. This is completely incorrect, but
287 // close enough for now.
288 GenericValue GV;
289 GV.IntVal = APInt(32, strlen(FmtStr));
290 while (1) {
291 switch (*FmtStr) {
292 case 0: return GV; // Null terminator...
293 default: // Normal nonspecial character
294 sprintf(OutputBuffer++, "%c", *FmtStr++);
295 break;
296 case '\\': { // Handle escape codes
297 sprintf(OutputBuffer, "%c%c", *FmtStr, *(FmtStr+1));
298 FmtStr += 2; OutputBuffer += 2;
299 break;
300 }
301 case '%': { // Handle format specifiers
302 char FmtBuf[100] = "", Buffer[1000] = "";
303 char *FB = FmtBuf;
304 *FB++ = *FmtStr++;
305 char Last = *FB++ = *FmtStr++;
306 unsigned HowLong = 0;
307 while (Last != 'c' && Last != 'd' && Last != 'i' && Last != 'u' &&
308 Last != 'o' && Last != 'x' && Last != 'X' && Last != 'e' &&
309 Last != 'E' && Last != 'g' && Last != 'G' && Last != 'f' &&
310 Last != 'p' && Last != 's' && Last != '%') {
311 if (Last == 'l' || Last == 'L') HowLong++; // Keep track of l's
312 Last = *FB++ = *FmtStr++;
313 }
314 *FB = 0;
315
316 switch (Last) {
317 case '%':
318 sprintf(Buffer, FmtBuf); break;
319 case 'c':
320 sprintf(Buffer, FmtBuf, uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
321 break;
322 case 'd': case 'i':
323 case 'u': case 'o':
324 case 'x': case 'X':
325 if (HowLong >= 1) {
326 if (HowLong == 1 &&
327 TheInterpreter->getTargetData()->getPointerSizeInBits() == 64 &&
328 sizeof(long) < sizeof(int64_t)) {
329 // Make sure we use %lld with a 64 bit argument because we might be
330 // compiling LLI on a 32 bit compiler.
331 unsigned Size = strlen(FmtBuf);
332 FmtBuf[Size] = FmtBuf[Size-1];
333 FmtBuf[Size+1] = 0;
334 FmtBuf[Size-1] = 'l';
335 }
336 sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal.getZExtValue());
337 } else
338 sprintf(Buffer, FmtBuf,uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
339 break;
340 case 'e': case 'E': case 'g': case 'G': case 'f':
341 sprintf(Buffer, FmtBuf, Args[ArgNo++].DoubleVal); break;
342 case 'p':
343 sprintf(Buffer, FmtBuf, (void*)GVTOP(Args[ArgNo++])); break;
344 case 's':
345 sprintf(Buffer, FmtBuf, (char*)GVTOP(Args[ArgNo++])); break;
346 default: cerr << "<unknown printf code '" << *FmtStr << "'!>";
347 ArgNo++; break;
348 }
349 strcpy(OutputBuffer, Buffer);
350 OutputBuffer += strlen(Buffer);
351 }
352 break;
353 }
354 }
355 return GV;
356}
357
358// int printf(sbyte *, ...) - a very rough implementation to make output useful.
359GenericValue lle_X_printf(FunctionType *FT, const vector<GenericValue> &Args) {
360 char Buffer[10000];
361 vector<GenericValue> NewArgs;
362 NewArgs.push_back(PTOGV((void*)&Buffer[0]));
363 NewArgs.insert(NewArgs.end(), Args.begin(), Args.end());
364 GenericValue GV = lle_X_sprintf(FT, NewArgs);
365 cout << Buffer;
366 return GV;
367}
368
369static void ByteswapSCANFResults(const char *Fmt, void *Arg0, void *Arg1,
370 void *Arg2, void *Arg3, void *Arg4, void *Arg5,
371 void *Arg6, void *Arg7, void *Arg8) {
372 void *Args[] = { Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, 0 };
373
374 // Loop over the format string, munging read values as appropriate (performs
375 // byteswaps as necessary).
376 unsigned ArgNo = 0;
377 while (*Fmt) {
378 if (*Fmt++ == '%') {
379 // Read any flag characters that may be present...
380 bool Suppress = false;
381 bool Half = false;
382 bool Long = false;
383 bool LongLong = false; // long long or long double
384
385 while (1) {
386 switch (*Fmt++) {
387 case '*': Suppress = true; break;
388 case 'a': /*Allocate = true;*/ break; // We don't need to track this
389 case 'h': Half = true; break;
390 case 'l': Long = true; break;
391 case 'q':
392 case 'L': LongLong = true; break;
393 default:
394 if (Fmt[-1] > '9' || Fmt[-1] < '0') // Ignore field width specs
395 goto Out;
396 }
397 }
398 Out:
399
400 // Read the conversion character
401 if (!Suppress && Fmt[-1] != '%') { // Nothing to do?
402 unsigned Size = 0;
403 const Type *Ty = 0;
404
405 switch (Fmt[-1]) {
406 case 'i': case 'o': case 'u': case 'x': case 'X': case 'n': case 'p':
407 case 'd':
408 if (Long || LongLong) {
409 Size = 8; Ty = Type::Int64Ty;
410 } else if (Half) {
411 Size = 4; Ty = Type::Int16Ty;
412 } else {
413 Size = 4; Ty = Type::Int32Ty;
414 }
415 break;
416
417 case 'e': case 'g': case 'E':
418 case 'f':
419 if (Long || LongLong) {
420 Size = 8; Ty = Type::DoubleTy;
421 } else {
422 Size = 4; Ty = Type::FloatTy;
423 }
424 break;
425
426 case 's': case 'c': case '[': // No byteswap needed
427 Size = 1;
428 Ty = Type::Int8Ty;
429 break;
430
431 default: break;
432 }
433
434 if (Size) {
435 GenericValue GV;
436 void *Arg = Args[ArgNo++];
437 memcpy(&GV, Arg, Size);
438 TheInterpreter->StoreValueToMemory(GV, (GenericValue*)Arg, Ty);
439 }
440 }
441 }
442 }
443}
444
445// int sscanf(const char *format, ...);
446GenericValue lle_X_sscanf(FunctionType *FT, const vector<GenericValue> &args) {
447 assert(args.size() < 10 && "Only handle up to 10 args to sscanf right now!");
448
449 char *Args[10];
450 for (unsigned i = 0; i < args.size(); ++i)
451 Args[i] = (char*)GVTOP(args[i]);
452
453 GenericValue GV;
454 GV.IntVal = APInt(32, sscanf(Args[0], Args[1], Args[2], Args[3], Args[4],
455 Args[5], Args[6], Args[7], Args[8], Args[9]));
456 ByteswapSCANFResults(Args[1], Args[2], Args[3], Args[4],
457 Args[5], Args[6], Args[7], Args[8], Args[9], 0);
458 return GV;
459}
460
461// int scanf(const char *format, ...);
462GenericValue lle_X_scanf(FunctionType *FT, const vector<GenericValue> &args) {
463 assert(args.size() < 10 && "Only handle up to 10 args to scanf right now!");
464
465 char *Args[10];
466 for (unsigned i = 0; i < args.size(); ++i)
467 Args[i] = (char*)GVTOP(args[i]);
468
469 GenericValue GV;
470 GV.IntVal = APInt(32, scanf( Args[0], Args[1], Args[2], Args[3], Args[4],
471 Args[5], Args[6], Args[7], Args[8], Args[9]));
472 ByteswapSCANFResults(Args[0], Args[1], Args[2], Args[3], Args[4],
473 Args[5], Args[6], Args[7], Args[8], Args[9]);
474 return GV;
475}
476
477
478// int clock(void) - Profiling implementation
479GenericValue lle_i_clock(FunctionType *FT, const vector<GenericValue> &Args) {
480 extern unsigned int clock(void);
481 GenericValue GV;
482 GV.IntVal = APInt(32, clock());
483 return GV;
484}
485
486
487//===----------------------------------------------------------------------===//
488// String Functions...
489//===----------------------------------------------------------------------===//
490
491// int strcmp(const char *S1, const char *S2);
492GenericValue lle_X_strcmp(FunctionType *FT, const vector<GenericValue> &Args) {
493 assert(Args.size() == 2);
494 GenericValue Ret;
495 Ret.IntVal = APInt(32, strcmp((char*)GVTOP(Args[0]), (char*)GVTOP(Args[1])));
496 return Ret;
497}
498
499// char *strcat(char *Dest, const char *src);
500GenericValue lle_X_strcat(FunctionType *FT, const vector<GenericValue> &Args) {
501 assert(Args.size() == 2);
502 assert(isa<PointerType>(FT->getReturnType()) &&"strcat must return pointer");
503 return PTOGV(strcat((char*)GVTOP(Args[0]), (char*)GVTOP(Args[1])));
504}
505
506// char *strcpy(char *Dest, const char *src);
507GenericValue lle_X_strcpy(FunctionType *FT, const vector<GenericValue> &Args) {
508 assert(Args.size() == 2);
509 assert(isa<PointerType>(FT->getReturnType()) &&"strcpy must return pointer");
510 return PTOGV(strcpy((char*)GVTOP(Args[0]), (char*)GVTOP(Args[1])));
511}
512
513static GenericValue size_t_to_GV (size_t n) {
514 GenericValue Ret;
515 if (sizeof (size_t) == sizeof (uint64_t)) {
516 Ret.IntVal = APInt(64, n);
517 } else {
518 assert (sizeof (size_t) == sizeof (unsigned int));
519 Ret.IntVal = APInt(32, n);
520 }
521 return Ret;
522}
523
524static size_t GV_to_size_t (GenericValue GV) {
525 size_t count;
526 if (sizeof (size_t) == sizeof (uint64_t)) {
527 count = (size_t)GV.IntVal.getZExtValue();
528 } else {
529 assert (sizeof (size_t) == sizeof (unsigned int));
530 count = (size_t)GV.IntVal.getZExtValue();
531 }
532 return count;
533}
534
535// size_t strlen(const char *src);
536GenericValue lle_X_strlen(FunctionType *FT, const vector<GenericValue> &Args) {
537 assert(Args.size() == 1);
538 size_t strlenResult = strlen ((char *) GVTOP (Args[0]));
539 return size_t_to_GV (strlenResult);
540}
541
542// char *strdup(const char *src);
543GenericValue lle_X_strdup(FunctionType *FT, const vector<GenericValue> &Args) {
544 assert(Args.size() == 1);
545 assert(isa<PointerType>(FT->getReturnType()) && "strdup must return pointer");
546 return PTOGV(strdup((char*)GVTOP(Args[0])));
547}
548
549// char *__strdup(const char *src);
550GenericValue lle_X___strdup(FunctionType *FT, const vector<GenericValue> &Args) {
551 assert(Args.size() == 1);
552 assert(isa<PointerType>(FT->getReturnType()) &&"_strdup must return pointer");
553 return PTOGV(strdup((char*)GVTOP(Args[0])));
554}
555
556// void *memset(void *S, int C, size_t N)
557GenericValue lle_X_memset(FunctionType *FT, const vector<GenericValue> &Args) {
558 assert(Args.size() == 3);
559 size_t count = GV_to_size_t (Args[2]);
560 assert(isa<PointerType>(FT->getReturnType()) && "memset must return pointer");
561 return PTOGV(memset(GVTOP(Args[0]), uint32_t(Args[1].IntVal.getZExtValue()),
562 count));
563}
564
565// void *memcpy(void *Dest, void *src, size_t Size);
566GenericValue lle_X_memcpy(FunctionType *FT, const vector<GenericValue> &Args) {
567 assert(Args.size() == 3);
568 assert(isa<PointerType>(FT->getReturnType()) && "memcpy must return pointer");
569 size_t count = GV_to_size_t (Args[2]);
570 return PTOGV(memcpy((char*)GVTOP(Args[0]), (char*)GVTOP(Args[1]), count));
571}
572
573//===----------------------------------------------------------------------===//
574// IO Functions...
575//===----------------------------------------------------------------------===//
576
577// getFILE - Turn a pointer in the host address space into a legit pointer in
578// the interpreter address space. This is an identity transformation.
579#define getFILE(ptr) ((FILE*)ptr)
580
581// FILE *fopen(const char *filename, const char *mode);
582GenericValue lle_X_fopen(FunctionType *FT, const vector<GenericValue> &Args) {
583 assert(Args.size() == 2);
584 assert(isa<PointerType>(FT->getReturnType()) && "fopen must return pointer");
585 return PTOGV(fopen((const char *)GVTOP(Args[0]),
586 (const char *)GVTOP(Args[1])));
587}
588
589// int fclose(FILE *F);
590GenericValue lle_X_fclose(FunctionType *FT, const vector<GenericValue> &Args) {
591 assert(Args.size() == 1);
592 GenericValue GV;
593 GV.IntVal = APInt(32, fclose(getFILE(GVTOP(Args[0]))));
594 return GV;
595}
596
597// int feof(FILE *stream);
598GenericValue lle_X_feof(FunctionType *FT, const vector<GenericValue> &Args) {
599 assert(Args.size() == 1);
600 GenericValue GV;
601
602 GV.IntVal = APInt(32, feof(getFILE(GVTOP(Args[0]))));
603 return GV;
604}
605
606// size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
607GenericValue lle_X_fread(FunctionType *FT, const vector<GenericValue> &Args) {
608 assert(Args.size() == 4);
609 size_t result;
610
611 result = fread((void*)GVTOP(Args[0]), GV_to_size_t (Args[1]),
612 GV_to_size_t (Args[2]), getFILE(GVTOP(Args[3])));
613 return size_t_to_GV (result);
614}
615
616// size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);
617GenericValue lle_X_fwrite(FunctionType *FT, const vector<GenericValue> &Args) {
618 assert(Args.size() == 4);
619 size_t result;
620
621 result = fwrite((void*)GVTOP(Args[0]), GV_to_size_t (Args[1]),
622 GV_to_size_t (Args[2]), getFILE(GVTOP(Args[3])));
623 return size_t_to_GV (result);
624}
625
626// char *fgets(char *s, int n, FILE *stream);
627GenericValue lle_X_fgets(FunctionType *FT, const vector<GenericValue> &Args) {
628 assert(Args.size() == 3);
629 return GVTOP(fgets((char*)GVTOP(Args[0]), Args[1].IntVal.getZExtValue(),
630 getFILE(GVTOP(Args[2]))));
631}
632
633// FILE *freopen(const char *path, const char *mode, FILE *stream);
634GenericValue lle_X_freopen(FunctionType *FT, const vector<GenericValue> &Args) {
635 assert(Args.size() == 3);
636 assert(isa<PointerType>(FT->getReturnType()) &&"freopen must return pointer");
637 return PTOGV(freopen((char*)GVTOP(Args[0]), (char*)GVTOP(Args[1]),
638 getFILE(GVTOP(Args[2]))));
639}
640
641// int fflush(FILE *stream);
642GenericValue lle_X_fflush(FunctionType *FT, const vector<GenericValue> &Args) {
643 assert(Args.size() == 1);
644 GenericValue GV;
645 GV.IntVal = APInt(32, fflush(getFILE(GVTOP(Args[0]))));
646 return GV;
647}
648
649// int getc(FILE *stream);
650GenericValue lle_X_getc(FunctionType *FT, const vector<GenericValue> &Args) {
651 assert(Args.size() == 1);
652 GenericValue GV;
653 GV.IntVal = APInt(32, getc(getFILE(GVTOP(Args[0]))));
654 return GV;
655}
656
657// int _IO_getc(FILE *stream);
658GenericValue lle_X__IO_getc(FunctionType *F, const vector<GenericValue> &Args) {
659 return lle_X_getc(F, Args);
660}
661
662// int fputc(int C, FILE *stream);
663GenericValue lle_X_fputc(FunctionType *FT, const vector<GenericValue> &Args) {
664 assert(Args.size() == 2);
665 GenericValue GV;
666 GV.IntVal = APInt(32, fputc(Args[0].IntVal.getZExtValue(),
667 getFILE(GVTOP(Args[1]))));
668 return GV;
669}
670
671// int ungetc(int C, FILE *stream);
672GenericValue lle_X_ungetc(FunctionType *FT, const vector<GenericValue> &Args) {
673 assert(Args.size() == 2);
674 GenericValue GV;
675 GV.IntVal = APInt(32, ungetc(Args[0].IntVal.getZExtValue(),
676 getFILE(GVTOP(Args[1]))));
677 return GV;
678}
679
680// int ferror (FILE *stream);
681GenericValue lle_X_ferror(FunctionType *FT, const vector<GenericValue> &Args) {
682 assert(Args.size() == 1);
683 GenericValue GV;
684 GV.IntVal = APInt(32, ferror (getFILE(GVTOP(Args[0]))));
685 return GV;
686}
687
688// int fprintf(FILE *,sbyte *, ...) - a very rough implementation to make output
689// useful.
690GenericValue lle_X_fprintf(FunctionType *FT, const vector<GenericValue> &Args) {
691 assert(Args.size() >= 2);
692 char Buffer[10000];
693 vector<GenericValue> NewArgs;
694 NewArgs.push_back(PTOGV(Buffer));
695 NewArgs.insert(NewArgs.end(), Args.begin()+1, Args.end());
696 GenericValue GV = lle_X_sprintf(FT, NewArgs);
697
698 fputs(Buffer, getFILE(GVTOP(Args[0])));
699 return GV;
700}
701
702} // End extern "C"
703
704
705void Interpreter::initializeExternalFunctions() {
706 FuncNames["lle_X_putchar"] = lle_X_putchar;
707 FuncNames["lle_X__IO_putc"] = lle_X__IO_putc;
708 FuncNames["lle_X_exit"] = lle_X_exit;
709 FuncNames["lle_X_abort"] = lle_X_abort;
710 FuncNames["lle_X_malloc"] = lle_X_malloc;
711 FuncNames["lle_X_calloc"] = lle_X_calloc;
712 FuncNames["lle_X_realloc"] = lle_X_realloc;
713 FuncNames["lle_X_free"] = lle_X_free;
714 FuncNames["lle_X_atoi"] = lle_X_atoi;
715 FuncNames["lle_X_pow"] = lle_X_pow;
716 FuncNames["lle_X_exp"] = lle_X_exp;
717 FuncNames["lle_X_log"] = lle_X_log;
718 FuncNames["lle_X_floor"] = lle_X_floor;
719 FuncNames["lle_X_srand"] = lle_X_srand;
720 FuncNames["lle_X_rand"] = lle_X_rand;
721#ifdef HAVE_RAND48
722 FuncNames["lle_X_drand48"] = lle_X_drand48;
723 FuncNames["lle_X_srand48"] = lle_X_srand48;
724 FuncNames["lle_X_lrand48"] = lle_X_lrand48;
725#endif
726 FuncNames["lle_X_sqrt"] = lle_X_sqrt;
727 FuncNames["lle_X_puts"] = lle_X_puts;
728 FuncNames["lle_X_printf"] = lle_X_printf;
729 FuncNames["lle_X_sprintf"] = lle_X_sprintf;
730 FuncNames["lle_X_sscanf"] = lle_X_sscanf;
731 FuncNames["lle_X_scanf"] = lle_X_scanf;
732 FuncNames["lle_i_clock"] = lle_i_clock;
733
734 FuncNames["lle_X_strcmp"] = lle_X_strcmp;
735 FuncNames["lle_X_strcat"] = lle_X_strcat;
736 FuncNames["lle_X_strcpy"] = lle_X_strcpy;
737 FuncNames["lle_X_strlen"] = lle_X_strlen;
738 FuncNames["lle_X___strdup"] = lle_X___strdup;
739 FuncNames["lle_X_memset"] = lle_X_memset;
740 FuncNames["lle_X_memcpy"] = lle_X_memcpy;
741
742 FuncNames["lle_X_fopen"] = lle_X_fopen;
743 FuncNames["lle_X_fclose"] = lle_X_fclose;
744 FuncNames["lle_X_feof"] = lle_X_feof;
745 FuncNames["lle_X_fread"] = lle_X_fread;
746 FuncNames["lle_X_fwrite"] = lle_X_fwrite;
747 FuncNames["lle_X_fgets"] = lle_X_fgets;
748 FuncNames["lle_X_fflush"] = lle_X_fflush;
749 FuncNames["lle_X_fgetc"] = lle_X_getc;
750 FuncNames["lle_X_getc"] = lle_X_getc;
751 FuncNames["lle_X__IO_getc"] = lle_X__IO_getc;
752 FuncNames["lle_X_fputc"] = lle_X_fputc;
753 FuncNames["lle_X_ungetc"] = lle_X_ungetc;
754 FuncNames["lle_X_fprintf"] = lle_X_fprintf;
755 FuncNames["lle_X_freopen"] = lle_X_freopen;
756}
757