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