1 //===-- ExternalFunctions.cpp - Implement External Functions --------------===// 2 // 3 // This file contains both code to deal with invoking "external" functions, but 4 // also contains code that implements "exported" external functions. 5 // 6 // External functions in LLI are implemented by dlopen'ing the lli executable 7 // and using dlsym to look op the functions that we want to invoke. If a 8 // function is found, then the arguments are mangled and passed in to the 9 // function call. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "Interpreter.h" 14 #include "ExecutionAnnotations.h" 15 #include "llvm/Module.h" 16 #include "llvm/DerivedTypes.h" 17 #include "llvm/SymbolTable.h" 18 #include "llvm/Target/TargetData.h" 19 #include <map> 20 #include <dlfcn.h> 21 #include <link.h> 22 #include <math.h> 23 #include <stdio.h> 24 using std::vector; 25 using std::cout; 26 27 typedef GenericValue (*ExFunc)(FunctionType *, const vector<GenericValue> &); 28 static std::map<const Function *, ExFunc> Functions; 29 static std::map<std::string, ExFunc> FuncNames; 30 31 static Interpreter *TheInterpreter; 32 33 // getCurrentExecutablePath() - Return the directory that the lli executable 34 // lives in. 35 // 36 std::string Interpreter::getCurrentExecutablePath() const { 37 Dl_info Info; 38 if (dladdr(&TheInterpreter, &Info) == 0) return ""; 39 40 std::string LinkAddr(Info.dli_fname); 41 unsigned SlashPos = LinkAddr.rfind('/'); 42 if (SlashPos != std::string::npos) 43 LinkAddr.resize(SlashPos); // Trim the executable name off... 44 45 return LinkAddr; 46 } 47 48 49 static char getTypeID(const Type *Ty) { 50 switch (Ty->getPrimitiveID()) { 51 case Type::VoidTyID: return 'V'; 52 case Type::BoolTyID: return 'o'; 53 case Type::UByteTyID: return 'B'; 54 case Type::SByteTyID: return 'b'; 55 case Type::UShortTyID: return 'S'; 56 case Type::ShortTyID: return 's'; 57 case Type::UIntTyID: return 'I'; 58 case Type::IntTyID: return 'i'; 59 case Type::ULongTyID: return 'L'; 60 case Type::LongTyID: return 'l'; 61 case Type::FloatTyID: return 'F'; 62 case Type::DoubleTyID: return 'D'; 63 case Type::PointerTyID: return 'P'; 64 case Type::FunctionTyID: return 'M'; 65 case Type::StructTyID: return 'T'; 66 case Type::ArrayTyID: return 'A'; 67 case Type::OpaqueTyID: return 'O'; 68 default: return 'U'; 69 } 70 } 71 72 static ExFunc lookupFunction(const Function *M) { 73 // Function not found, look it up... start by figuring out what the 74 // composite function name should be. 75 std::string ExtName = "lle_"; 76 const FunctionType *MT = M->getFunctionType(); 77 for (unsigned i = 0; const Type *Ty = MT->getContainedType(i); ++i) 78 ExtName += getTypeID(Ty); 79 ExtName += "_" + M->getName(); 80 81 //cout << "Tried: '" << ExtName << "'\n"; 82 ExFunc FnPtr = FuncNames[ExtName]; 83 if (FnPtr == 0) 84 FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ExtName.c_str()); 85 if (FnPtr == 0) 86 FnPtr = FuncNames["lle_X_"+M->getName()]; 87 if (FnPtr == 0) // Try calling a generic function... if it exists... 88 FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ("lle_X_"+M->getName()).c_str()); 89 if (FnPtr != 0) 90 Functions.insert(std::make_pair(M, FnPtr)); // Cache for later 91 return FnPtr; 92 } 93 94 GenericValue Interpreter::callExternalMethod(Function *M, 95 const vector<GenericValue> &ArgVals) { 96 TheInterpreter = this; 97 98 // Do a lookup to see if the function is in our cache... this should just be a 99 // defered annotation! 100 std::map<const Function *, ExFunc>::iterator FI = Functions.find(M); 101 ExFunc Fn = (FI == Functions.end()) ? lookupFunction(M) : FI->second; 102 if (Fn == 0) { 103 cout << "Tried to execute an unknown external function: " 104 << M->getType()->getDescription() << " " << M->getName() << "\n"; 105 return GenericValue(); 106 } 107 108 // TODO: FIXME when types are not const! 109 GenericValue Result = Fn(const_cast<FunctionType*>(M->getFunctionType()), 110 ArgVals); 111 return Result; 112 } 113 114 115 //===----------------------------------------------------------------------===// 116 // Functions "exported" to the running application... 117 // 118 extern "C" { // Don't add C++ manglings to llvm mangling :) 119 120 // Implement void printstr([ubyte {x N}] *) 121 GenericValue lle_VP_printstr(FunctionType *M, 122 const vector<GenericValue> &ArgVal){ 123 assert(ArgVal.size() == 1 && "printstr only takes one argument!"); 124 cout << (char*)GVTOP(ArgVal[0]); 125 return GenericValue(); 126 } 127 128 // Implement 'void print(X)' for every type... 129 GenericValue lle_X_print(FunctionType *M, const vector<GenericValue> &ArgVals) { 130 assert(ArgVals.size() == 1 && "generic print only takes one argument!"); 131 132 Interpreter::print(M->getParamTypes()[0], ArgVals[0]); 133 return GenericValue(); 134 } 135 136 // Implement 'void printVal(X)' for every type... 137 GenericValue lle_X_printVal(FunctionType *M, 138 const vector<GenericValue> &ArgVal) { 139 assert(ArgVal.size() == 1 && "generic print only takes one argument!"); 140 141 // Specialize print([ubyte {x N} ] *) and print(sbyte *) 142 if (const PointerType *PTy = 143 dyn_cast<PointerType>(M->getParamTypes()[0].get())) 144 if (PTy->getElementType() == Type::SByteTy || 145 isa<ArrayType>(PTy->getElementType())) { 146 return lle_VP_printstr(M, ArgVal); 147 } 148 149 Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]); 150 return GenericValue(); 151 } 152 153 // Implement 'void printString(X)' 154 // Argument must be [ubyte {x N} ] * or sbyte * 155 GenericValue lle_X_printString(FunctionType *M, 156 const vector<GenericValue> &ArgVal) { 157 assert(ArgVal.size() == 1 && "generic print only takes one argument!"); 158 return lle_VP_printstr(M, ArgVal); 159 } 160 161 // Implement 'void print<TYPE>(X)' for each primitive type or pointer type 162 #define PRINT_TYPE_FUNC(TYPENAME,TYPEID) \ 163 GenericValue lle_X_print##TYPENAME(FunctionType *M,\ 164 const vector<GenericValue> &ArgVal) {\ 165 assert(ArgVal.size() == 1 && "generic print only takes one argument!");\ 166 assert(M->getParamTypes()[0].get()->getPrimitiveID() == Type::TYPEID);\ 167 Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);\ 168 return GenericValue();\ 169 } 170 171 PRINT_TYPE_FUNC(SByte, SByteTyID) 172 PRINT_TYPE_FUNC(UByte, UByteTyID) 173 PRINT_TYPE_FUNC(Short, ShortTyID) 174 PRINT_TYPE_FUNC(UShort, UShortTyID) 175 PRINT_TYPE_FUNC(Int, IntTyID) 176 PRINT_TYPE_FUNC(UInt, UIntTyID) 177 PRINT_TYPE_FUNC(Long, LongTyID) 178 PRINT_TYPE_FUNC(ULong, ULongTyID) 179 PRINT_TYPE_FUNC(Float, FloatTyID) 180 PRINT_TYPE_FUNC(Double, DoubleTyID) 181 PRINT_TYPE_FUNC(Pointer, PointerTyID) 182 183 184 // void putchar(sbyte) 185 GenericValue lle_Vb_putchar(FunctionType *M, const vector<GenericValue> &Args) { 186 cout << Args[0].SByteVal; 187 return GenericValue(); 188 } 189 190 // int putchar(int) 191 GenericValue lle_ii_putchar(FunctionType *M, const vector<GenericValue> &Args) { 192 cout << ((char)Args[0].IntVal) << std::flush; 193 return Args[0]; 194 } 195 196 // void putchar(ubyte) 197 GenericValue lle_VB_putchar(FunctionType *M, const vector<GenericValue> &Args) { 198 cout << Args[0].SByteVal << std::flush; 199 return Args[0]; 200 } 201 202 // void __main() 203 GenericValue lle_V___main(FunctionType *M, const vector<GenericValue> &Args) { 204 return GenericValue(); 205 } 206 207 // void exit(int) 208 GenericValue lle_X_exit(FunctionType *M, const vector<GenericValue> &Args) { 209 TheInterpreter->exitCalled(Args[0]); 210 return GenericValue(); 211 } 212 213 // void abort(void) 214 GenericValue lle_X_abort(FunctionType *M, const vector<GenericValue> &Args) { 215 std::cerr << "***PROGRAM ABORTED***!\n"; 216 GenericValue GV; 217 GV.IntVal = 1; 218 TheInterpreter->exitCalled(GV); 219 return GenericValue(); 220 } 221 222 // void *malloc(uint) 223 GenericValue lle_X_malloc(FunctionType *M, const vector<GenericValue> &Args) { 224 assert(Args.size() == 1 && "Malloc expects one argument!"); 225 return PTOGV(malloc(Args[0].UIntVal)); 226 } 227 228 // void free(void *) 229 GenericValue lle_X_free(FunctionType *M, const vector<GenericValue> &Args) { 230 assert(Args.size() == 1); 231 free(GVTOP(Args[0])); 232 return GenericValue(); 233 } 234 235 // int atoi(char *) 236 GenericValue lle_X_atoi(FunctionType *M, const vector<GenericValue> &Args) { 237 assert(Args.size() == 1); 238 GenericValue GV; 239 GV.IntVal = atoi((char*)GVTOP(Args[0])); 240 return GV; 241 } 242 243 // double pow(double, double) 244 GenericValue lle_X_pow(FunctionType *M, const vector<GenericValue> &Args) { 245 assert(Args.size() == 2); 246 GenericValue GV; 247 GV.DoubleVal = pow(Args[0].DoubleVal, Args[1].DoubleVal); 248 return GV; 249 } 250 251 // double exp(double) 252 GenericValue lle_X_exp(FunctionType *M, const vector<GenericValue> &Args) { 253 assert(Args.size() == 1); 254 GenericValue GV; 255 GV.DoubleVal = exp(Args[0].DoubleVal); 256 return GV; 257 } 258 259 // double sqrt(double) 260 GenericValue lle_X_sqrt(FunctionType *M, const vector<GenericValue> &Args) { 261 assert(Args.size() == 1); 262 GenericValue GV; 263 GV.DoubleVal = sqrt(Args[0].DoubleVal); 264 return GV; 265 } 266 267 // double log(double) 268 GenericValue lle_X_log(FunctionType *M, const vector<GenericValue> &Args) { 269 assert(Args.size() == 1); 270 GenericValue GV; 271 GV.DoubleVal = log(Args[0].DoubleVal); 272 return GV; 273 } 274 275 // int isnan(double value); 276 GenericValue lle_X_isnan(FunctionType *F, const vector<GenericValue> &Args) { 277 assert(Args.size() == 1); 278 GenericValue GV; 279 GV.IntVal = isnan(Args[0].DoubleVal); 280 return GV; 281 } 282 283 // double floor(double) 284 GenericValue lle_X_floor(FunctionType *M, const vector<GenericValue> &Args) { 285 assert(Args.size() == 1); 286 GenericValue GV; 287 GV.DoubleVal = floor(Args[0].DoubleVal); 288 return GV; 289 } 290 291 // double drand48() 292 GenericValue lle_X_drand48(FunctionType *M, const vector<GenericValue> &Args) { 293 assert(Args.size() == 0); 294 GenericValue GV; 295 GV.DoubleVal = drand48(); 296 return GV; 297 } 298 299 // long lrand48() 300 GenericValue lle_X_lrand48(FunctionType *M, const vector<GenericValue> &Args) { 301 assert(Args.size() == 0); 302 GenericValue GV; 303 GV.IntVal = lrand48(); 304 return GV; 305 } 306 307 // void srand48(long) 308 GenericValue lle_X_srand48(FunctionType *M, const vector<GenericValue> &Args) { 309 assert(Args.size() == 1); 310 srand48(Args[0].IntVal); 311 return GenericValue(); 312 } 313 314 // void srand(uint) 315 GenericValue lle_X_srand(FunctionType *M, const vector<GenericValue> &Args) { 316 assert(Args.size() == 1); 317 srand(Args[0].UIntVal); 318 return GenericValue(); 319 } 320 321 // int puts(const char*) 322 GenericValue lle_X_puts(FunctionType *M, const vector<GenericValue> &Args) { 323 assert(Args.size() == 1); 324 GenericValue GV; 325 GV.IntVal = puts((char*)GVTOP(Args[0])); 326 return GV; 327 } 328 329 // int sprintf(sbyte *, sbyte *, ...) - a very rough implementation to make 330 // output useful. 331 GenericValue lle_X_sprintf(FunctionType *M, const vector<GenericValue> &Args) { 332 char *OutputBuffer = (char *)GVTOP(Args[0]); 333 const char *FmtStr = (const char *)GVTOP(Args[1]); 334 unsigned ArgNo = 2; 335 336 // printf should return # chars printed. This is completely incorrect, but 337 // close enough for now. 338 GenericValue GV; GV.IntVal = strlen(FmtStr); 339 while (1) { 340 switch (*FmtStr) { 341 case 0: return GV; // Null terminator... 342 default: // Normal nonspecial character 343 sprintf(OutputBuffer++, "%c", *FmtStr++); 344 break; 345 case '\\': { // Handle escape codes 346 sprintf(OutputBuffer, "%c%c", *FmtStr, *(FmtStr+1)); 347 FmtStr += 2; OutputBuffer += 2; 348 break; 349 } 350 case '%': { // Handle format specifiers 351 char FmtBuf[100] = "", Buffer[1000] = ""; 352 char *FB = FmtBuf; 353 *FB++ = *FmtStr++; 354 char Last = *FB++ = *FmtStr++; 355 unsigned HowLong = 0; 356 while (Last != 'c' && Last != 'd' && Last != 'i' && Last != 'u' && 357 Last != 'o' && Last != 'x' && Last != 'X' && Last != 'e' && 358 Last != 'E' && Last != 'g' && Last != 'G' && Last != 'f' && 359 Last != 'p' && Last != 's' && Last != '%') { 360 if (Last == 'l' || Last == 'L') HowLong++; // Keep track of l's 361 Last = *FB++ = *FmtStr++; 362 } 363 *FB = 0; 364 365 switch (Last) { 366 case '%': 367 sprintf(Buffer, FmtBuf); break; 368 case 'c': 369 sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal); break; 370 case 'd': case 'i': 371 case 'u': case 'o': 372 case 'x': case 'X': 373 if (HowLong >= 1) { 374 if (HowLong == 1) { 375 // Make sure we use %lld with a 64 bit argument because we might be 376 // compiling LLI on a 32 bit compiler. 377 unsigned Size = strlen(FmtBuf); 378 FmtBuf[Size] = FmtBuf[Size-1]; 379 FmtBuf[Size+1] = 0; 380 FmtBuf[Size-1] = 'l'; 381 } 382 sprintf(Buffer, FmtBuf, Args[ArgNo++].ULongVal); 383 } else 384 sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal); break; 385 case 'e': case 'E': case 'g': case 'G': case 'f': 386 sprintf(Buffer, FmtBuf, Args[ArgNo++].DoubleVal); break; 387 case 'p': 388 sprintf(Buffer, FmtBuf, (void*)GVTOP(Args[ArgNo++])); break; 389 case 's': 390 sprintf(Buffer, FmtBuf, (char*)GVTOP(Args[ArgNo++])); break; 391 default: cout << "<unknown printf code '" << *FmtStr << "'!>"; 392 ArgNo++; break; 393 } 394 strcpy(OutputBuffer, Buffer); 395 OutputBuffer += strlen(Buffer); 396 } 397 break; 398 } 399 } 400 } 401 402 // int printf(sbyte *, ...) - a very rough implementation to make output useful. 403 GenericValue lle_X_printf(FunctionType *M, const vector<GenericValue> &Args) { 404 char Buffer[10000]; 405 vector<GenericValue> NewArgs; 406 NewArgs.push_back(PTOGV(Buffer)); 407 NewArgs.insert(NewArgs.end(), Args.begin(), Args.end()); 408 GenericValue GV = lle_X_sprintf(M, NewArgs); 409 cout << Buffer; 410 return GV; 411 } 412 413 // int sscanf(const char *format, ...); 414 GenericValue lle_X_sscanf(FunctionType *M, const vector<GenericValue> &args) { 415 assert(args.size() < 10 && "Only handle up to 10 args to sscanf right now!"); 416 417 const char *Args[10]; 418 for (unsigned i = 0; i < args.size(); ++i) 419 Args[i] = (const char*)GVTOP(args[i]); 420 421 GenericValue GV; 422 GV.IntVal = sscanf(Args[0], Args[1], Args[2], Args[3], Args[4], 423 Args[5], Args[6], Args[7], Args[8], Args[9]); 424 return GV; 425 } 426 427 428 // int clock(void) - Profiling implementation 429 GenericValue lle_i_clock(FunctionType *M, const vector<GenericValue> &Args) { 430 extern int clock(void); 431 GenericValue GV; GV.IntVal = clock(); 432 return GV; 433 } 434 435 //===----------------------------------------------------------------------===// 436 // IO Functions... 437 //===----------------------------------------------------------------------===// 438 439 // getFILE - Turn a pointer in the host address space into a legit pointer in 440 // the interpreter address space. For the most part, this is an identity 441 // transformation, but if the program refers to stdio, stderr, stdin then they 442 // have pointers that are relative to the __iob array. If this is the case, 443 // change the FILE into the REAL stdio stream. 444 // 445 static FILE *getFILE(void *Ptr) { 446 static Module *LastMod = 0; 447 static PointerTy IOBBase = 0; 448 static unsigned FILESize; 449 450 if (LastMod != &TheInterpreter->getModule()) { // Module change or initialize? 451 Module *M = LastMod = &TheInterpreter->getModule(); 452 453 // Check to see if the currently loaded module contains an __iob symbol... 454 GlobalVariable *IOB = 0; 455 SymbolTable &ST = M->getSymbolTable(); 456 for (SymbolTable::iterator I = ST.begin(), E = ST.end(); I != E; ++I) { 457 SymbolTable::VarMap &M = I->second; 458 for (SymbolTable::VarMap::iterator J = M.begin(), E = M.end(); 459 J != E; ++J) 460 if (J->first == "__iob") 461 if ((IOB = dyn_cast<GlobalVariable>(J->second))) 462 break; 463 if (IOB) break; 464 } 465 466 #if 0 /// FIXME! __iob support for LLI 467 // If we found an __iob symbol now, find out what the actual address it's 468 // held in is... 469 if (IOB) { 470 // Get the address the array lives in... 471 GlobalAddress *Address = 472 (GlobalAddress*)IOB->getOrCreateAnnotation(GlobalAddressAID); 473 IOBBase = (PointerTy)(GenericValue*)Address->Ptr; 474 475 // Figure out how big each element of the array is... 476 const ArrayType *AT = 477 dyn_cast<ArrayType>(IOB->getType()->getElementType()); 478 if (AT) 479 FILESize = TD.getTypeSize(AT->getElementType()); 480 else 481 FILESize = 16*8; // Default size 482 } 483 #endif 484 } 485 486 // Check to see if this is a reference to __iob... 487 if (IOBBase) { 488 unsigned FDNum = ((unsigned long)Ptr-IOBBase)/FILESize; 489 if (FDNum == 0) 490 return stdin; 491 else if (FDNum == 1) 492 return stdout; 493 else if (FDNum == 2) 494 return stderr; 495 } 496 497 return (FILE*)Ptr; 498 } 499 500 501 // FILE *fopen(const char *filename, const char *mode); 502 GenericValue lle_X_fopen(FunctionType *M, const vector<GenericValue> &Args) { 503 assert(Args.size() == 2); 504 return PTOGV(fopen((const char *)GVTOP(Args[0]), 505 (const char *)GVTOP(Args[1]))); 506 } 507 508 // int fclose(FILE *F); 509 GenericValue lle_X_fclose(FunctionType *M, const vector<GenericValue> &Args) { 510 assert(Args.size() == 1); 511 GenericValue GV; 512 GV.IntVal = fclose(getFILE(GVTOP(Args[0]))); 513 return GV; 514 } 515 516 // int feof(FILE *stream); 517 GenericValue lle_X_feof(FunctionType *M, const vector<GenericValue> &Args) { 518 assert(Args.size() == 1); 519 GenericValue GV; 520 521 GV.IntVal = feof(getFILE(GVTOP(Args[0]))); 522 return GV; 523 } 524 525 // size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream); 526 GenericValue lle_X_fread(FunctionType *M, const vector<GenericValue> &Args) { 527 assert(Args.size() == 4); 528 GenericValue GV; 529 530 GV.UIntVal = fread((void*)GVTOP(Args[0]), Args[1].UIntVal, 531 Args[2].UIntVal, getFILE(GVTOP(Args[3]))); 532 return GV; 533 } 534 535 // size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream); 536 GenericValue lle_X_fwrite(FunctionType *M, const vector<GenericValue> &Args) { 537 assert(Args.size() == 4); 538 GenericValue GV; 539 540 GV.UIntVal = fwrite((void*)GVTOP(Args[0]), Args[1].UIntVal, 541 Args[2].UIntVal, getFILE(GVTOP(Args[3]))); 542 return GV; 543 } 544 545 // char *fgets(char *s, int n, FILE *stream); 546 GenericValue lle_X_fgets(FunctionType *M, const vector<GenericValue> &Args) { 547 assert(Args.size() == 3); 548 return GVTOP(fgets((char*)GVTOP(Args[0]), Args[1].IntVal, 549 getFILE(GVTOP(Args[2])))); 550 } 551 552 // FILE *freopen(const char *path, const char *mode, FILE *stream); 553 GenericValue lle_X_freopen(FunctionType *M, const vector<GenericValue> &Args) { 554 assert(Args.size() == 3); 555 return PTOGV(freopen((char*)GVTOP(Args[0]), (char*)GVTOP(Args[1]), 556 getFILE(GVTOP(Args[2])))); 557 } 558 559 // int fflush(FILE *stream); 560 GenericValue lle_X_fflush(FunctionType *M, const vector<GenericValue> &Args) { 561 assert(Args.size() == 1); 562 GenericValue GV; 563 GV.IntVal = fflush(getFILE(GVTOP(Args[0]))); 564 return GV; 565 } 566 567 // int getc(FILE *stream); 568 GenericValue lle_X_getc(FunctionType *M, const vector<GenericValue> &Args) { 569 assert(Args.size() == 1); 570 GenericValue GV; 571 GV.IntVal = getc(getFILE(GVTOP(Args[0]))); 572 return GV; 573 } 574 575 // int fputc(int C, FILE *stream); 576 GenericValue lle_X_fputc(FunctionType *M, const vector<GenericValue> &Args) { 577 assert(Args.size() == 2); 578 GenericValue GV; 579 GV.IntVal = fputc(Args[0].IntVal, getFILE(GVTOP(Args[1]))); 580 return GV; 581 } 582 583 // int ungetc(int C, FILE *stream); 584 GenericValue lle_X_ungetc(FunctionType *M, const vector<GenericValue> &Args) { 585 assert(Args.size() == 2); 586 GenericValue GV; 587 GV.IntVal = ungetc(Args[0].IntVal, getFILE(GVTOP(Args[1]))); 588 return GV; 589 } 590 591 // int fprintf(FILE *,sbyte *, ...) - a very rough implementation to make output 592 // useful. 593 GenericValue lle_X_fprintf(FunctionType *M, const vector<GenericValue> &Args) { 594 assert(Args.size() > 2); 595 char Buffer[10000]; 596 vector<GenericValue> NewArgs; 597 NewArgs.push_back(PTOGV(Buffer)); 598 NewArgs.insert(NewArgs.end(), Args.begin()+1, Args.end()); 599 GenericValue GV = lle_X_sprintf(M, NewArgs); 600 601 fputs(Buffer, getFILE(GVTOP(Args[0]))); 602 return GV; 603 } 604 605 } // End extern "C" 606 607 608 void Interpreter::initializeExternalMethods() { 609 FuncNames["lle_VP_printstr"] = lle_VP_printstr; 610 FuncNames["lle_X_print"] = lle_X_print; 611 FuncNames["lle_X_printVal"] = lle_X_printVal; 612 FuncNames["lle_X_printString"] = lle_X_printString; 613 FuncNames["lle_X_printUByte"] = lle_X_printUByte; 614 FuncNames["lle_X_printSByte"] = lle_X_printSByte; 615 FuncNames["lle_X_printUShort"] = lle_X_printUShort; 616 FuncNames["lle_X_printShort"] = lle_X_printShort; 617 FuncNames["lle_X_printInt"] = lle_X_printInt; 618 FuncNames["lle_X_printUInt"] = lle_X_printUInt; 619 FuncNames["lle_X_printLong"] = lle_X_printLong; 620 FuncNames["lle_X_printULong"] = lle_X_printULong; 621 FuncNames["lle_X_printFloat"] = lle_X_printFloat; 622 FuncNames["lle_X_printDouble"] = lle_X_printDouble; 623 FuncNames["lle_X_printPointer"] = lle_X_printPointer; 624 FuncNames["lle_Vb_putchar"] = lle_Vb_putchar; 625 FuncNames["lle_ii_putchar"] = lle_ii_putchar; 626 FuncNames["lle_VB_putchar"] = lle_VB_putchar; 627 FuncNames["lle_V___main"] = lle_V___main; 628 FuncNames["lle_X_exit"] = lle_X_exit; 629 FuncNames["lle_X_abort"] = lle_X_abort; 630 FuncNames["lle_X_malloc"] = lle_X_malloc; 631 FuncNames["lle_X_free"] = lle_X_free; 632 FuncNames["lle_X_atoi"] = lle_X_atoi; 633 FuncNames["lle_X_pow"] = lle_X_pow; 634 FuncNames["lle_X_exp"] = lle_X_exp; 635 FuncNames["lle_X_log"] = lle_X_log; 636 FuncNames["lle_X_isnan"] = lle_X_isnan; 637 FuncNames["lle_X_floor"] = lle_X_floor; 638 FuncNames["lle_X_srand"] = lle_X_srand; 639 FuncNames["lle_X_drand48"] = lle_X_drand48; 640 FuncNames["lle_X_srand48"] = lle_X_srand48; 641 FuncNames["lle_X_lrand48"] = lle_X_lrand48; 642 FuncNames["lle_X_sqrt"] = lle_X_sqrt; 643 FuncNames["lle_X_puts"] = lle_X_puts; 644 FuncNames["lle_X_printf"] = lle_X_printf; 645 FuncNames["lle_X_sprintf"] = lle_X_sprintf; 646 FuncNames["lle_X_sscanf"] = lle_X_sscanf; 647 FuncNames["lle_i_clock"] = lle_i_clock; 648 FuncNames["lle_X_fopen"] = lle_X_fopen; 649 FuncNames["lle_X_fclose"] = lle_X_fclose; 650 FuncNames["lle_X_feof"] = lle_X_feof; 651 FuncNames["lle_X_fread"] = lle_X_fread; 652 FuncNames["lle_X_fwrite"] = lle_X_fwrite; 653 FuncNames["lle_X_fgets"] = lle_X_fgets; 654 FuncNames["lle_X_fflush"] = lle_X_fflush; 655 FuncNames["lle_X_fgetc"] = lle_X_getc; 656 FuncNames["lle_X_getc"] = lle_X_getc; 657 FuncNames["lle_X_fputc"] = lle_X_fputc; 658 FuncNames["lle_X_ungetc"] = lle_X_ungetc; 659 FuncNames["lle_X_fprintf"] = lle_X_fprintf; 660 FuncNames["lle_X_freopen"] = lle_X_freopen; 661 } 662