1 /* 2 * Android "Almost" C Compiler. 3 * This is a compiler for a small subset of the C language, intended for use 4 * in scripting environments where speed and memory footprint are important. 5 * 6 * This code is based upon the "unobfuscated" version of the 7 * Obfuscated Tiny C compiler, see the file LICENSE for details. 8 * 9 */ 10 11 #define LOG_TAG "acc" 12 #include <cutils/log.h> 13 14 #include <ctype.h> 15 #include <errno.h> 16 #include <limits.h> 17 #include <stdarg.h> 18 #include <stdint.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 #include <unistd.h> 23 24 #include <cutils/hashmap.h> 25 26 #include <sys/mman.h> 27 28 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) 29 #define MAP_ANONYMOUS MAP_ANON 30 #endif 31 32 #if defined(__arm__) 33 #define DEFAULT_ARM_CODEGEN 34 #define PROVIDE_ARM_CODEGEN 35 #elif defined(__i386__) 36 #define DEFAULT_X86_CODEGEN 37 #define PROVIDE_X86_CODEGEN 38 #elif defined(__x86_64__) 39 #define DEFAULT_X64_CODEGEN 40 #define PROVIDE_X64_CODEGEN 41 #endif 42 43 #if (defined(__VFP_FP__) && !defined(__SOFTFP__)) 44 #define ARM_USE_VFP 45 #endif 46 47 #include <acc/acc.h> 48 49 #define LOG_API(...) do {} while(0) 50 // #define LOG_API(...) fprintf (stderr, __VA_ARGS__) 51 52 #define LOG_STACK(...) do {} while(0) 53 // #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__) 54 55 // #define PROVIDE_TRACE_CODEGEN 56 57 // Uncomment to disable ARM peephole optimizations 58 // #define DISABLE_ARM_PEEPHOLE 59 60 // Uncomment to save input to a text file in DEBUG_DUMP_PATTERN 61 // #define DEBUG_SAVE_INPUT_TO_FILE 62 63 #ifdef DEBUG_SAVE_INPUT_TO_FILE 64 #ifdef ARM_USE_VFP 65 #define DEBUG_DUMP_PATTERN "/data/misc/acc_dump/%d.c" 66 #else 67 #define DEBUG_DUMP_PATTERN "/tmp/acc_dump/%d.c" 68 #endif 69 #endif 70 71 #define assert(b) assertImpl(b, __LINE__) 72 73 namespace acc { 74 75 // Subset of STL vector. 76 template<class E> class Vector { 77 public: 78 Vector() { 79 mpBase = 0; 80 mUsed = 0; 81 mSize = 0; 82 } 83 84 ~Vector() { 85 if (mpBase) { 86 clear(); 87 free(mpBase); 88 } 89 } 90 91 inline E& operator[](size_t i) { 92 return mpBase[i]; 93 } 94 95 inline E& front() { 96 return mpBase[0]; 97 } 98 99 inline E& back() { 100 return mpBase[mUsed - 1]; 101 } 102 103 void pop_back() { 104 mUsed -= 1; 105 mpBase[mUsed].~E(); 106 } 107 108 void push_back(const E& item) { 109 * ensure(1) = item; 110 } 111 112 inline size_t size() { 113 return mUsed; 114 } 115 116 void clear() { 117 if (mpBase) { 118 size_t used = mUsed; 119 for(size_t i = 0; i < used; i++) { 120 mpBase[i].~E(); 121 } 122 } 123 mUsed = 0; 124 } 125 126 private: 127 E* ensure(int n) { 128 size_t newUsed = mUsed + n; 129 if (newUsed > mSize) { 130 size_t newSize = mSize * 2 + 10; 131 if (newSize < newUsed) { 132 newSize = newUsed; 133 } 134 mpBase = (E*) realloc(mpBase, sizeof(E) * newSize); 135 mSize = newSize; 136 } 137 E* result = mpBase + mUsed; 138 mUsed = newUsed; 139 return result; 140 } 141 142 E* mpBase; 143 size_t mUsed; 144 size_t mSize; 145 }; 146 147 class ErrorSink { 148 public: 149 void error(const char *fmt, ...) { 150 va_list ap; 151 va_start(ap, fmt); 152 verror(fmt, ap); 153 va_end(ap); 154 } 155 156 virtual ~ErrorSink() {} 157 virtual void verror(const char* fmt, va_list ap) = 0; 158 }; 159 160 class Compiler : public ErrorSink { 161 typedef int tokenid_t; 162 enum TypeTag { 163 TY_UNKNOWN = -1, 164 TY_INT, // 0 165 TY_CHAR, // 1 166 TY_SHORT, // 2 167 TY_VOID, // 3 168 TY_FLOAT, // 4 169 TY_DOUBLE, // 5 170 TY_POINTER, // 6 171 TY_ARRAY, // 7 172 TY_STRUCT, // 8 173 TY_FUNC, // 9 174 TY_PARAM // 10 175 }; 176 177 enum StorageClass { 178 SC_DEFAULT, // 0 179 SC_AUTO, // 1 180 SC_REGISTER, // 2 181 SC_STATIC, // 3 182 SC_EXTERN, // 4 183 SC_TYPEDEF // 5 184 }; 185 186 struct Type { 187 TypeTag tag; 188 StorageClass storageClass; 189 tokenid_t id; // For function arguments, global vars, local vars, struct elements 190 tokenid_t structTag; // For structs the name of the struct 191 int length; // length of array, offset of struct element. -1 means struct is forward defined 192 int alignment; // for structs only 193 Type* pHead; // For a struct this is the prototype struct. 194 Type* pTail; 195 }; 196 197 enum ExpressionType { 198 ET_RVALUE, 199 ET_LVALUE 200 }; 201 202 struct ExpressionValue { 203 ExpressionValue() { 204 et = ET_RVALUE; 205 pType = NULL; 206 } 207 ExpressionType et; 208 Type* pType; 209 }; 210 211 class ICodeBuf { 212 public: 213 virtual ~ICodeBuf() {} 214 virtual void init(int size) = 0; 215 virtual void setErrorSink(ErrorSink* pErrorSink) = 0; 216 virtual void o4(int n) = 0; 217 virtual void ob(int n) = 0; 218 virtual void* getBase() = 0; 219 virtual intptr_t getSize() = 0; 220 virtual intptr_t getPC() = 0; 221 // Call this before trying to modify code in the buffer. 222 virtual void flush() = 0; 223 }; 224 225 class CodeBuf : public ICodeBuf { 226 char* ind; // Output code pointer 227 char* pProgramBase; 228 ErrorSink* mErrorSink; 229 int mSize; 230 bool mOverflowed; 231 232 void release() { 233 if (pProgramBase != 0) { 234 munmap(pProgramBase, mSize); 235 pProgramBase = 0; 236 } 237 } 238 239 bool check(int n) { 240 int newSize = ind - pProgramBase + n; 241 bool overflow = newSize > mSize; 242 if (overflow && !mOverflowed) { 243 mOverflowed = true; 244 if (mErrorSink) { 245 mErrorSink->error("Code too large: %d bytes", newSize); 246 } 247 } 248 return overflow; 249 } 250 251 public: 252 CodeBuf() { 253 pProgramBase = 0; 254 ind = 0; 255 mErrorSink = 0; 256 mSize = 0; 257 mOverflowed = false; 258 } 259 260 virtual ~CodeBuf() { 261 release(); 262 } 263 264 virtual void init(int size) { 265 release(); 266 mSize = size; 267 pProgramBase = (char*) mmap(NULL, size, 268 PROT_EXEC | PROT_READ | PROT_WRITE, 269 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 270 ind = pProgramBase; 271 } 272 273 virtual void setErrorSink(ErrorSink* pErrorSink) { 274 mErrorSink = pErrorSink; 275 } 276 277 virtual void o4(int n) { 278 if(check(4)) { 279 return; 280 } 281 * (int*) ind = n; 282 ind += 4; 283 } 284 285 /* 286 * Output a byte. Handles all values, 0..ff. 287 */ 288 virtual void ob(int n) { 289 if(check(1)) { 290 return; 291 } 292 *ind++ = n; 293 } 294 295 virtual void* getBase() { 296 return (void*) pProgramBase; 297 } 298 299 virtual intptr_t getSize() { 300 return ind - pProgramBase; 301 } 302 303 virtual intptr_t getPC() { 304 return (intptr_t) ind; 305 } 306 307 virtual void flush() {} 308 }; 309 310 /** 311 * A code generator creates an in-memory program, generating the code on 312 * the fly. There is one code generator implementation for each supported 313 * architecture. 314 * 315 * The code generator implements the following abstract machine: 316 * R0 - the accumulator. 317 * FP - a frame pointer for accessing function arguments and local 318 * variables. 319 * SP - a stack pointer for storing intermediate results while evaluating 320 * expressions. The stack pointer grows downwards. 321 * 322 * The function calling convention is that all arguments are placed on the 323 * stack such that the first argument has the lowest address. 324 * After the call, the result is in R0. The caller is responsible for 325 * removing the arguments from the stack. 326 * The R0 register is not saved across function calls. The 327 * FP and SP registers are saved. 328 */ 329 330 class CodeGenerator { 331 public: 332 CodeGenerator() { 333 mErrorSink = 0; 334 pCodeBuf = 0; 335 pushType(); 336 } 337 virtual ~CodeGenerator() {} 338 339 virtual void init(ICodeBuf* pCodeBuf) { 340 this->pCodeBuf = pCodeBuf; 341 pCodeBuf->setErrorSink(mErrorSink); 342 } 343 344 virtual void setErrorSink(ErrorSink* pErrorSink) { 345 mErrorSink = pErrorSink; 346 if (pCodeBuf) { 347 pCodeBuf->setErrorSink(mErrorSink); 348 } 349 } 350 351 /* Give the code generator some utility types so it can 352 * use its own types as needed for the results of some 353 * operations like gcmp. 354 */ 355 356 void setTypes(Type* pInt) { 357 mkpInt = pInt; 358 } 359 360 /* Emit a function prolog. 361 * pDecl is the function declaration, which gives the arguments. 362 * Save the old value of the FP. 363 * Set the new value of the FP. 364 * Convert from the native platform calling convention to 365 * our stack-based calling convention. This may require 366 * pushing arguments from registers to the stack. 367 * Allocate "N" bytes of stack space. N isn't known yet, so 368 * just emit the instructions for adjusting the stack, and return 369 * the address to patch up. The patching will be done in 370 * functionExit(). 371 * returns address to patch with local variable size. 372 */ 373 virtual int functionEntry(Type* pDecl) = 0; 374 375 /* Emit a function epilog. 376 * Restore the old SP and FP register values. 377 * Return to the calling function. 378 * argCount - the number of arguments to the function. 379 * localVariableAddress - returned from functionEntry() 380 * localVariableSize - the size in bytes of the local variables. 381 */ 382 virtual void functionExit(Type* pDecl, int localVariableAddress, 383 int localVariableSize) = 0; 384 385 /* load immediate value to R0 */ 386 virtual void li(int i) = 0; 387 388 /* Load floating point value from global address. */ 389 virtual void loadFloat(int address, Type* pType) = 0; 390 391 /* Add the struct offset in bytes to R0, change the type to pType */ 392 virtual void addStructOffsetR0(int offset, Type* pType) = 0; 393 394 /* Jump to a target, and return the address of the word that 395 * holds the target data, in case it needs to be fixed up later. 396 */ 397 virtual int gjmp(int t) = 0; 398 399 /* Test R0 and jump to a target if the test succeeds. 400 * l = 0: je, l == 1: jne 401 * Return the address of the word that holds the targed data, in 402 * case it needs to be fixed up later. 403 */ 404 virtual int gtst(bool l, int t) = 0; 405 406 /* Compare TOS against R0, and store the boolean result in R0. 407 * Pops TOS. 408 * op specifies the comparison. 409 */ 410 virtual void gcmp(int op) = 0; 411 412 /* Perform the arithmetic op specified by op. TOS is the 413 * left argument, R0 is the right argument. 414 * Pops TOS. 415 */ 416 virtual void genOp(int op) = 0; 417 418 /* Compare 0 against R0, and store the boolean result in R0. 419 * op specifies the comparison. 420 */ 421 virtual void gUnaryCmp(int op) = 0; 422 423 /* Perform the arithmetic op specified by op. 0 is the 424 * left argument, R0 is the right argument. 425 */ 426 virtual void genUnaryOp(int op) = 0; 427 428 /* Push R0 onto the stack. (Also known as "dup" for duplicate.) 429 */ 430 virtual void pushR0() = 0; 431 432 /* Turn R0, TOS into R0 TOS R0 */ 433 434 virtual void over() = 0; 435 436 /* Pop R0 from the stack. (Also known as "drop") 437 */ 438 virtual void popR0() = 0; 439 440 /* Store R0 to the address stored in TOS. 441 * The TOS is popped. 442 */ 443 virtual void storeR0ToTOS() = 0; 444 445 /* Load R0 from the address stored in R0. 446 */ 447 virtual void loadR0FromR0() = 0; 448 449 /* Load the absolute address of a variable to R0. 450 * If ea <= LOCAL, then this is a local variable, or an 451 * argument, addressed relative to FP. 452 * else it is an absolute global address. 453 * 454 * et is ET_RVALUE for things like string constants, ET_LVALUE for 455 * variables. 456 */ 457 virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) = 0; 458 459 /* Load the pc-relative address of a forward-referenced variable to R0. 460 * Return the address of the 4-byte constant so that it can be filled 461 * in later. 462 */ 463 virtual int leaForward(int ea, Type* pPointerType) = 0; 464 465 /** 466 * Convert R0 to the given type. 467 */ 468 469 void convertR0(Type* pType) { 470 convertR0Imp(pType, false); 471 } 472 473 void castR0(Type* pType) { 474 convertR0Imp(pType, true); 475 } 476 477 virtual void convertR0Imp(Type* pType, bool isCast) = 0; 478 479 /* Emit code to adjust the stack for a function call. Return the 480 * label for the address of the instruction that adjusts the 481 * stack size. This will be passed as argument "a" to 482 * endFunctionCallArguments. 483 */ 484 virtual int beginFunctionCallArguments() = 0; 485 486 /* Emit code to store R0 to the stack at byte offset l. 487 * Returns stack size of object (typically 4 or 8 bytes) 488 */ 489 virtual size_t storeR0ToArg(int l, Type* pArgType) = 0; 490 491 /* Patch the function call preamble. 492 * a is the address returned from beginFunctionCallArguments 493 * l is the number of bytes the arguments took on the stack. 494 * Typically you would also emit code to convert the argument 495 * list into whatever the native function calling convention is. 496 * On ARM for example you would pop the first 5 arguments into 497 * R0..R4 498 */ 499 virtual void endFunctionCallArguments(Type* pDecl, int a, int l) = 0; 500 501 /* Emit a call to an unknown function. The argument "symbol" needs to 502 * be stored in the location where the address should go. It forms 503 * a chain. The address will be patched later. 504 * Return the address of the word that has to be patched. 505 */ 506 virtual int callForward(int symbol, Type* pFunc) = 0; 507 508 /* Call a function pointer. L is the number of bytes the arguments 509 * take on the stack. The address of the function is stored at 510 * location SP + l. 511 */ 512 virtual void callIndirect(int l, Type* pFunc) = 0; 513 514 /* Adjust SP after returning from a function call. l is the 515 * number of bytes of arguments stored on the stack. isIndirect 516 * is true if this was an indirect call. (In which case the 517 * address of the function is stored at location SP + l.) 518 */ 519 virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) = 0; 520 521 /* Generate a symbol at the current PC. t is the head of a 522 * linked list of addresses to patch. 523 */ 524 virtual void gsym(int t) = 0; 525 526 /* Resolve a forward reference function at the current PC. 527 * t is the head of a 528 * linked list of addresses to patch. 529 * (Like gsym, but using absolute address, not PC relative address.) 530 */ 531 virtual void resolveForward(int t) = 0; 532 533 /* 534 * Do any cleanup work required at the end of a compile. 535 * For example, an instruction cache might need to be 536 * invalidated. 537 * Return non-zero if there is an error. 538 */ 539 virtual int finishCompile() = 0; 540 541 /** 542 * Adjust relative branches by this amount. 543 */ 544 virtual int jumpOffset() = 0; 545 546 /** 547 * Memory alignment (in bytes) for this type of data 548 */ 549 virtual size_t alignmentOf(Type* type) = 0; 550 551 /** 552 * Array element alignment (in bytes) for this type of data. 553 */ 554 virtual size_t sizeOf(Type* type) = 0; 555 556 virtual Type* getR0Type() { 557 return mExpressionStack.back().pType; 558 } 559 560 virtual ExpressionType getR0ExpressionType() { 561 return mExpressionStack.back().et; 562 } 563 564 virtual void setR0ExpressionType(ExpressionType et) { 565 mExpressionStack.back().et = et; 566 } 567 568 virtual size_t getExpressionStackDepth() { 569 return mExpressionStack.size(); 570 } 571 572 virtual void forceR0RVal() { 573 if (getR0ExpressionType() == ET_LVALUE) { 574 loadR0FromR0(); 575 } 576 } 577 578 protected: 579 /* 580 * Output a byte. Handles all values, 0..ff. 581 */ 582 void ob(int n) { 583 pCodeBuf->ob(n); 584 } 585 586 void o4(int data) { 587 pCodeBuf->o4(data); 588 } 589 590 intptr_t getBase() { 591 return (intptr_t) pCodeBuf->getBase(); 592 } 593 594 intptr_t getPC() { 595 return pCodeBuf->getPC(); 596 } 597 598 intptr_t getSize() { 599 return pCodeBuf->getSize(); 600 } 601 602 void flush() { 603 pCodeBuf->flush(); 604 } 605 606 void error(const char* fmt,...) { 607 va_list ap; 608 va_start(ap, fmt); 609 mErrorSink->verror(fmt, ap); 610 va_end(ap); 611 } 612 613 void assertImpl(bool test, int line) { 614 if (!test) { 615 error("code generator assertion failed at line %s:%d.", __FILE__, line); 616 LOGD("code generator assertion failed at line %s:%d.", __FILE__, line); 617 * (char*) 0 = 0; 618 } 619 } 620 621 void setR0Type(Type* pType) { 622 assert(pType != NULL); 623 mExpressionStack.back().pType = pType; 624 mExpressionStack.back().et = ET_RVALUE; 625 } 626 627 void setR0Type(Type* pType, ExpressionType et) { 628 assert(pType != NULL); 629 mExpressionStack.back().pType = pType; 630 mExpressionStack.back().et = et; 631 } 632 633 Type* getTOSType() { 634 return mExpressionStack[mExpressionStack.size()-2].pType; 635 } 636 637 void pushType() { 638 if (mExpressionStack.size()) { 639 mExpressionStack.push_back(mExpressionStack.back()); 640 } else { 641 mExpressionStack.push_back(ExpressionValue()); 642 } 643 644 } 645 646 void overType() { 647 size_t size = mExpressionStack.size(); 648 if (size >= 2) { 649 mExpressionStack.push_back(mExpressionStack.back()); 650 mExpressionStack[size-1] = mExpressionStack[size-2]; 651 mExpressionStack[size-2] = mExpressionStack[size]; 652 } 653 } 654 655 void popType() { 656 mExpressionStack.pop_back(); 657 } 658 659 bool bitsSame(Type* pA, Type* pB) { 660 return collapseType(pA->tag) == collapseType(pB->tag); 661 } 662 663 TypeTag collapseType(TypeTag tag) { 664 static const TypeTag collapsedTag[] = { 665 TY_INT, 666 TY_INT, 667 TY_INT, 668 TY_VOID, 669 TY_FLOAT, 670 TY_DOUBLE, 671 TY_INT, 672 TY_INT, 673 TY_VOID, 674 TY_VOID, 675 TY_VOID 676 }; 677 return collapsedTag[tag]; 678 } 679 680 TypeTag collapseTypeR0() { 681 return collapseType(getR0Type()->tag); 682 } 683 684 static bool isFloatType(Type* pType) { 685 return isFloatTag(pType->tag); 686 } 687 688 static bool isFloatTag(TypeTag tag) { 689 return tag == TY_FLOAT || tag == TY_DOUBLE; 690 } 691 692 static bool isPointerType(Type* pType) { 693 return isPointerTag(pType->tag); 694 } 695 696 static bool isPointerTag(TypeTag tag) { 697 return tag == TY_POINTER || tag == TY_ARRAY; 698 } 699 700 Type* getPointerArithmeticResultType(Type* a, Type* b) { 701 TypeTag aTag = a->tag; 702 TypeTag bTag = b->tag; 703 if (aTag == TY_POINTER) { 704 return a; 705 } 706 if (bTag == TY_POINTER) { 707 return b; 708 } 709 if (aTag == TY_ARRAY) { 710 return a->pTail; 711 } 712 if (bTag == TY_ARRAY) { 713 return b->pTail; 714 } 715 return NULL; 716 } 717 Type* mkpInt; 718 719 private: 720 Vector<ExpressionValue> mExpressionStack; 721 ICodeBuf* pCodeBuf; 722 ErrorSink* mErrorSink; 723 }; 724 725 #ifdef PROVIDE_ARM_CODEGEN 726 727 static size_t rotateRight(size_t n, size_t rotate) { 728 return (n >> rotate) | (n << (32 - rotate)); 729 } 730 731 static size_t rotateLeft(size_t n, size_t rotate) { 732 return (n << rotate) | (n >> (32 - rotate)); 733 } 734 735 static bool encode12BitImmediate(size_t immediate, size_t* pResult) { 736 for(size_t i = 0; i < 16; i++) { 737 size_t rotate = i * 2; 738 size_t mask = rotateRight(0xff, rotate); 739 if ((immediate | mask) == mask) { 740 size_t bits8 = rotateLeft(immediate, rotate); 741 // assert(bits8 <= 0xff); 742 *pResult = (i << 8) | bits8; 743 return true; 744 } 745 } 746 return false; 747 } 748 749 static size_t decode12BitImmediate(size_t immediate) { 750 size_t data = immediate & 0xff; 751 size_t rotate = 2 * ((immediate >> 8) & 0xf); 752 return rotateRight(data, rotate); 753 } 754 755 static bool isPowerOfTwo(size_t n) { 756 return (n != 0) & ((n & (n-1)) == 0); 757 } 758 759 static size_t log2(size_t n) { 760 int result = 0; 761 while (n >>= 1) { 762 result++; 763 } 764 return result; 765 } 766 767 class ARMCodeBuf : public ICodeBuf { 768 ICodeBuf* mpBase; 769 ErrorSink* mErrorSink; 770 771 class CircularQueue { 772 static const int SIZE = 16; // Must be power of 2 773 static const int MASK = SIZE-1; 774 unsigned int mBuf[SIZE]; 775 int mHead; 776 int mCount; 777 778 public: 779 CircularQueue() { 780 mHead = 0; 781 mCount = 0; 782 } 783 784 void pushBack(unsigned int data) { 785 mBuf[(mHead + mCount) & MASK] = data; 786 mCount += 1; 787 } 788 789 unsigned int popFront() { 790 unsigned int result = mBuf[mHead]; 791 mHead = (mHead + 1) & MASK; 792 mCount -= 1; 793 return result; 794 } 795 796 void popBack(int n) { 797 mCount -= n; 798 } 799 800 inline int count() { 801 return mCount; 802 } 803 804 bool empty() { 805 return mCount == 0; 806 } 807 808 bool full() { 809 return mCount == SIZE; 810 } 811 812 // The valid indexes are 1 - count() to 0 813 unsigned int operator[](int i) { 814 return mBuf[(mHead + mCount + i) & MASK]; 815 } 816 }; 817 818 CircularQueue mQ; 819 820 void error(const char* fmt,...) { 821 va_list ap; 822 va_start(ap, fmt); 823 mErrorSink->verror(fmt, ap); 824 va_end(ap); 825 } 826 827 void flush() { 828 while (!mQ.empty()) { 829 mpBase->o4(mQ.popFront()); 830 } 831 mpBase->flush(); 832 } 833 834 public: 835 ARMCodeBuf(ICodeBuf* pBase) { 836 mpBase = pBase; 837 } 838 839 virtual ~ARMCodeBuf() { 840 delete mpBase; 841 } 842 843 void init(int size) { 844 mpBase->init(size); 845 } 846 847 void setErrorSink(ErrorSink* pErrorSink) { 848 mErrorSink = pErrorSink; 849 mpBase->setErrorSink(pErrorSink); 850 } 851 852 void o4(int n) { 853 if (mQ.full()) { 854 mpBase->o4(mQ.popFront()); 855 } 856 mQ.pushBack(n); 857 858 #ifndef DISABLE_ARM_PEEPHOLE 859 // Peephole check 860 bool didPeep; 861 do { 862 static const unsigned int opMask = 0x01e00000; 863 static const unsigned int immediateMask = 0x00000fff; 864 static const unsigned int BMask = 0x00400000; 865 didPeep = false; 866 if (mQ.count() >= 4) { 867 868 // Operand by a small constant 869 // push;mov #imm;pop;op ==> op #imm 870 871 if (mQ[-4] == 0xe92d0001 && // stmfd r13!, {r0} 872 (mQ[-3] & ~immediateMask) == 0xe3a00000 && // mov r0, #X 873 mQ[-2] == 0xe8bd0002 && // ldmea r13!, {r1} 874 (mQ[-1] & ~opMask) == (0xe0810000 & ~opMask)) { // OP r0, r1, r0 875 unsigned int movConst = mQ[-3]; 876 unsigned int op = mQ[-1]; 877 unsigned int combined = 0xe2000000 | (op & opMask) | (movConst & immediateMask); 878 // fprintf(stderr, "op %x movConst %x combined %x\n", op, movConst, combined); 879 if (! (combined == 0xe2800000 || combined == 0xe2400000)) { // add/sub #0 880 mQ.popBack(4); 881 mQ.pushBack(combined); 882 didPeep = true; 883 } else { 884 mQ.popBack(4); 885 didPeep = true; 886 } 887 } 888 } 889 890 // Load local variable 891 // sub r0,r11,#imm;ldr/ldrb r0,[r0] ==> ldr/ldrb r0, [r11,#-imm] 892 if (mQ.count() >= 2) { 893 if ((mQ[-2] & ~immediateMask) == 0xe24b0000) { // sub r0,r11,#imm 894 const unsigned int encodedImmediate = mQ[-2] & immediateMask; 895 const unsigned int ld = mQ[-1]; 896 if ((ld & ~BMask) == 0xe5900000) { // ldr{b} r0, [r0] 897 unsigned int combined = encodedImmediate | (0xE51B0000 | (ld & BMask)); // ldr r0, [r11, #-0] 898 mQ.popBack(2); 899 mQ.pushBack(combined); 900 didPeep = true; 901 } else if (ld == 0xedd07a00) { // ldcl p10, c7, [r0, #0x000] 902 unsigned int decodedImmediate = decode12BitImmediate(encodedImmediate); 903 if (decodedImmediate <= 1020 && ((decodedImmediate & 3) == 0)) { 904 unsigned int combined = (decodedImmediate >> 2) | 0xed5b7a00; // ldcl p10, c7, [r11, #-0] 905 mQ.popBack(2); 906 mQ.pushBack(combined); 907 didPeep = true; 908 } 909 } 910 } 911 } 912 913 // Constant array lookup 914 915 if (mQ.count() >= 6 && 916 mQ[-6] == 0xe92d0001 && // stmfd r13!, {r0} 917 (mQ[-5] & ~immediateMask)== 0xe3a00000 && // mov r0, #0x00000001 918 mQ[-4] == 0xe8bd0002 && // ldmea r13!, {r1} 919 (mQ[-3] & ~immediateMask)== 0xe3a02000 && // mov r2, #0x00000004 920 mQ[-2] == 0xe0000092 && // mul r0, r2, r0 921 mQ[-1] == 0xe0810000) { // add r0, r1, r0 922 unsigned int mov1 = mQ[-5]; 923 unsigned int mov2 = mQ[-3]; 924 unsigned int const1 = decode12BitImmediate(mov1); 925 unsigned int const2 = decode12BitImmediate(mov2); 926 unsigned int comboConst = const1 * const2; 927 size_t immediate = 0; 928 if (encode12BitImmediate(comboConst, &immediate)) { 929 mQ.popBack(6); 930 unsigned int add = immediate | 0xE2800000; // add r0, r0, #n 931 if (comboConst) { 932 mQ.pushBack(add); 933 } 934 didPeep = true; 935 } 936 } 937 938 // Pointer arithmetic with a stride that is a power of two 939 940 if (mQ.count() >= 3 && 941 (mQ[-3] & ~ immediateMask) == 0xe3a02000 && // mov r2, #stride 942 mQ[-2] == 0xe0000092 && // mul r0, r2, r0 943 mQ[-1] == 0xe0810000) { // add r0, r1, r0 944 int stride = decode12BitImmediate(mQ[-3]); 945 if (isPowerOfTwo(stride)) { 946 mQ.popBack(3); 947 unsigned int add = 0xe0810000 | (log2(stride) << 7); // add r0, r1, r0, LSL #log2(stride) 948 mQ.pushBack(add); 949 didPeep = true; 950 } 951 } 952 953 } while (didPeep); 954 #endif 955 } 956 957 void ob(int n) { 958 error("ob() not supported."); 959 } 960 961 void* getBase() { 962 flush(); 963 return mpBase->getBase(); 964 } 965 966 intptr_t getSize() { 967 flush(); 968 return mpBase->getSize(); 969 } 970 971 intptr_t getPC() { 972 flush(); 973 return mpBase->getPC(); 974 } 975 }; 976 977 class ARMCodeGenerator : public CodeGenerator { 978 public: 979 ARMCodeGenerator() { 980 #ifdef ARM_USE_VFP 981 // LOGD("Using ARM VFP hardware floating point."); 982 #else 983 // LOGD("Using ARM soft floating point."); 984 #endif 985 } 986 987 virtual ~ARMCodeGenerator() {} 988 989 /* returns address to patch with local variable size 990 */ 991 virtual int functionEntry(Type* pDecl) { 992 mStackUse = 0; 993 // sp -> arg4 arg5 ... 994 // Push our register-based arguments back on the stack 995 int regArgCount = calcRegArgCount(pDecl); 996 if (regArgCount > 0) { 997 mStackUse += regArgCount * 4; 998 o4(0xE92D0000 | ((1 << regArgCount) - 1)); // stmfd sp!, {} 999 } 1000 // sp -> arg0 arg1 ... 1001 o4(0xE92D4800); // stmfd sp!, {fp, lr} 1002 mStackUse += 2 * 4; 1003 // sp, fp -> oldfp, retadr, arg0 arg1 .... 1004 o4(0xE1A0B00D); // mov fp, sp 1005 LOG_STACK("functionEntry: %d\n", mStackUse); 1006 int pc = getPC(); 1007 o4(0xE24DD000); // sub sp, sp, # <local variables> 1008 // We don't know how many local variables we are going to use, 1009 // but we will round the allocation up to a multiple of 1010 // STACK_ALIGNMENT, so it won't affect the stack alignment. 1011 return pc; 1012 } 1013 1014 virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) { 1015 // Round local variable size up to a multiple of stack alignment 1016 localVariableSize = ((localVariableSize + STACK_ALIGNMENT - 1) / 1017 STACK_ALIGNMENT) * STACK_ALIGNMENT; 1018 // Patch local variable allocation code: 1019 if (localVariableSize < 0 || localVariableSize > 255) { 1020 error("localVariables out of range: %d", localVariableSize); 1021 } 1022 *(char*) (localVariableAddress) = localVariableSize; 1023 1024 #ifdef ARM_USE_VFP 1025 { 1026 Type* pReturnType = pDecl->pHead; 1027 switch(pReturnType->tag) { 1028 case TY_FLOAT: 1029 o4(0xEE170A90); // fmrs r0, s15 1030 break; 1031 case TY_DOUBLE: 1032 o4(0xEC510B17); // fmrrd r0, r1, d7 1033 break; 1034 default: 1035 break; 1036 } 1037 } 1038 #endif 1039 1040 // sp -> locals .... fp -> oldfp, retadr, arg0, arg1, ... 1041 o4(0xE1A0E00B); // mov lr, fp 1042 o4(0xE59BB000); // ldr fp, [fp] 1043 o4(0xE28ED004); // add sp, lr, #4 1044 // sp -> retadr, arg0, ... 1045 o4(0xE8BD4000); // ldmfd sp!, {lr} 1046 // sp -> arg0 .... 1047 1048 // We store the PC into the lr so we can adjust the sp before 1049 // returning. We need to pull off the registers we pushed 1050 // earlier. We don't need to actually store them anywhere, 1051 // just adjust the stack. 1052 int regArgCount = calcRegArgCount(pDecl); 1053 if (regArgCount) { 1054 o4(0xE28DD000 | (regArgCount << 2)); // add sp, sp, #argCount << 2 1055 } 1056 o4(0xE12FFF1E); // bx lr 1057 } 1058 1059 /* load immediate value */ 1060 virtual void li(int t) { 1061 liReg(t, 0); 1062 setR0Type(mkpInt); 1063 } 1064 1065 virtual void loadFloat(int address, Type* pType) { 1066 setR0Type(pType); 1067 // Global, absolute address 1068 o4(0xE59F0000); // ldr r0, .L1 1069 o4(0xEA000000); // b .L99 1070 o4(address); // .L1: .word ea 1071 // .L99: 1072 1073 switch (pType->tag) { 1074 case TY_FLOAT: 1075 #ifdef ARM_USE_VFP 1076 o4(0xEDD07A00); // flds s15, [r0] 1077 #else 1078 o4(0xE5900000); // ldr r0, [r0] 1079 #endif 1080 break; 1081 case TY_DOUBLE: 1082 #ifdef ARM_USE_VFP 1083 o4(0xED907B00); // fldd d7, [r0] 1084 #else 1085 o4(0xE1C000D0); // ldrd r0, [r0] 1086 #endif 1087 break; 1088 default: 1089 assert(false); 1090 break; 1091 } 1092 } 1093 1094 1095 virtual void addStructOffsetR0(int offset, Type* pType) { 1096 if (offset) { 1097 size_t immediate = 0; 1098 if (encode12BitImmediate(offset, &immediate)) { 1099 o4(0xE2800000 | immediate); // add r0, r0, #offset 1100 } else { 1101 error("structure offset out of range: %d", offset); 1102 } 1103 } 1104 setR0Type(pType, ET_LVALUE); 1105 } 1106 1107 virtual int gjmp(int t) { 1108 int pc = getPC(); 1109 o4(0xEA000000 | encodeAddress(t)); // b .L33 1110 return pc; 1111 } 1112 1113 /* l = 0: je, l == 1: jne */ 1114 virtual int gtst(bool l, int t) { 1115 Type* pR0Type = getR0Type(); 1116 TypeTag tagR0 = pR0Type->tag; 1117 switch(tagR0) { 1118 case TY_FLOAT: 1119 #ifdef ARM_USE_VFP 1120 o4(0xEEF57A40); // fcmpzs s15 1121 o4(0xEEF1FA10); // fmstat 1122 #else 1123 callRuntime((void*) runtime_is_non_zero_f); 1124 o4(0xE3500000); // cmp r0,#0 1125 #endif 1126 break; 1127 case TY_DOUBLE: 1128 #ifdef ARM_USE_VFP 1129 o4(0xEEB57B40); // fcmpzd d7 1130 o4(0xEEF1FA10); // fmstat 1131 #else 1132 callRuntime((void*) runtime_is_non_zero_d); 1133 o4(0xE3500000); // cmp r0,#0 1134 #endif 1135 break; 1136 default: 1137 o4(0xE3500000); // cmp r0,#0 1138 break; 1139 } 1140 int branch = l ? 0x1A000000 : 0x0A000000; // bne : beq 1141 int pc = getPC(); 1142 o4(branch | encodeAddress(t)); 1143 return pc; 1144 } 1145 1146 virtual void gcmp(int op) { 1147 Type* pR0Type = getR0Type(); 1148 Type* pTOSType = getTOSType(); 1149 TypeTag tagR0 = collapseType(pR0Type->tag); 1150 TypeTag tagTOS = collapseType(pTOSType->tag); 1151 if (tagR0 == TY_INT && tagTOS == TY_INT) { 1152 setupIntPtrArgs(); 1153 o4(0xE1510000); // cmp r1, r1 1154 switch(op) { 1155 case OP_EQUALS: 1156 o4(0x03A00001); // moveq r0,#1 1157 o4(0x13A00000); // movne r0,#0 1158 break; 1159 case OP_NOT_EQUALS: 1160 o4(0x03A00000); // moveq r0,#0 1161 o4(0x13A00001); // movne r0,#1 1162 break; 1163 case OP_LESS_EQUAL: 1164 o4(0xD3A00001); // movle r0,#1 1165 o4(0xC3A00000); // movgt r0,#0 1166 break; 1167 case OP_GREATER: 1168 o4(0xD3A00000); // movle r0,#0 1169 o4(0xC3A00001); // movgt r0,#1 1170 break; 1171 case OP_GREATER_EQUAL: 1172 o4(0xA3A00001); // movge r0,#1 1173 o4(0xB3A00000); // movlt r0,#0 1174 break; 1175 case OP_LESS: 1176 o4(0xA3A00000); // movge r0,#0 1177 o4(0xB3A00001); // movlt r0,#1 1178 break; 1179 default: 1180 error("Unknown comparison op %d", op); 1181 break; 1182 } 1183 } else if (tagR0 == TY_DOUBLE || tagTOS == TY_DOUBLE) { 1184 setupDoubleArgs(); 1185 #ifdef ARM_USE_VFP 1186 o4(0xEEB46BC7); // fcmped d6, d7 1187 o4(0xEEF1FA10); // fmstat 1188 switch(op) { 1189 case OP_EQUALS: 1190 o4(0x03A00001); // moveq r0,#1 1191 o4(0x13A00000); // movne r0,#0 1192 break; 1193 case OP_NOT_EQUALS: 1194 o4(0x03A00000); // moveq r0,#0 1195 o4(0x13A00001); // movne r0,#1 1196 break; 1197 case OP_LESS_EQUAL: 1198 o4(0xD3A00001); // movle r0,#1 1199 o4(0xC3A00000); // movgt r0,#0 1200 break; 1201 case OP_GREATER: 1202 o4(0xD3A00000); // movle r0,#0 1203 o4(0xC3A00001); // movgt r0,#1 1204 break; 1205 case OP_GREATER_EQUAL: 1206 o4(0xA3A00001); // movge r0,#1 1207 o4(0xB3A00000); // movlt r0,#0 1208 break; 1209 case OP_LESS: 1210 o4(0xA3A00000); // movge r0,#0 1211 o4(0xB3A00001); // movlt r0,#1 1212 break; 1213 default: 1214 error("Unknown comparison op %d", op); 1215 break; 1216 } 1217 #else 1218 switch(op) { 1219 case OP_EQUALS: 1220 callRuntime((void*) runtime_cmp_eq_dd); 1221 break; 1222 case OP_NOT_EQUALS: 1223 callRuntime((void*) runtime_cmp_ne_dd); 1224 break; 1225 case OP_LESS_EQUAL: 1226 callRuntime((void*) runtime_cmp_le_dd); 1227 break; 1228 case OP_GREATER: 1229 callRuntime((void*) runtime_cmp_gt_dd); 1230 break; 1231 case OP_GREATER_EQUAL: 1232 callRuntime((void*) runtime_cmp_ge_dd); 1233 break; 1234 case OP_LESS: 1235 callRuntime((void*) runtime_cmp_lt_dd); 1236 break; 1237 default: 1238 error("Unknown comparison op %d", op); 1239 break; 1240 } 1241 #endif 1242 } else { 1243 setupFloatArgs(); 1244 #ifdef ARM_USE_VFP 1245 o4(0xEEB47AE7); // fcmpes s14, s15 1246 o4(0xEEF1FA10); // fmstat 1247 switch(op) { 1248 case OP_EQUALS: 1249 o4(0x03A00001); // moveq r0,#1 1250 o4(0x13A00000); // movne r0,#0 1251 break; 1252 case OP_NOT_EQUALS: 1253 o4(0x03A00000); // moveq r0,#0 1254 o4(0x13A00001); // movne r0,#1 1255 break; 1256 case OP_LESS_EQUAL: 1257 o4(0xD3A00001); // movle r0,#1 1258 o4(0xC3A00000); // movgt r0,#0 1259 break; 1260 case OP_GREATER: 1261 o4(0xD3A00000); // movle r0,#0 1262 o4(0xC3A00001); // movgt r0,#1 1263 break; 1264 case OP_GREATER_EQUAL: 1265 o4(0xA3A00001); // movge r0,#1 1266 o4(0xB3A00000); // movlt r0,#0 1267 break; 1268 case OP_LESS: 1269 o4(0xA3A00000); // movge r0,#0 1270 o4(0xB3A00001); // movlt r0,#1 1271 break; 1272 default: 1273 error("Unknown comparison op %d", op); 1274 break; 1275 } 1276 #else 1277 switch(op) { 1278 case OP_EQUALS: 1279 callRuntime((void*) runtime_cmp_eq_ff); 1280 break; 1281 case OP_NOT_EQUALS: 1282 callRuntime((void*) runtime_cmp_ne_ff); 1283 break; 1284 case OP_LESS_EQUAL: 1285 callRuntime((void*) runtime_cmp_le_ff); 1286 break; 1287 case OP_GREATER: 1288 callRuntime((void*) runtime_cmp_gt_ff); 1289 break; 1290 case OP_GREATER_EQUAL: 1291 callRuntime((void*) runtime_cmp_ge_ff); 1292 break; 1293 case OP_LESS: 1294 callRuntime((void*) runtime_cmp_lt_ff); 1295 break; 1296 default: 1297 error("Unknown comparison op %d", op); 1298 break; 1299 } 1300 #endif 1301 } 1302 setR0Type(mkpInt); 1303 } 1304 1305 virtual void genOp(int op) { 1306 Type* pR0Type = getR0Type(); 1307 Type* pTOSType = getTOSType(); 1308 TypeTag tagR0 = pR0Type->tag; 1309 TypeTag tagTOS = pTOSType->tag; 1310 bool isFloatR0 = isFloatTag(tagR0); 1311 bool isFloatTOS = isFloatTag(tagTOS); 1312 if (!isFloatR0 && !isFloatTOS) { 1313 setupIntPtrArgs(); 1314 bool isPtrR0 = isPointerTag(tagR0); 1315 bool isPtrTOS = isPointerTag(tagTOS); 1316 if (isPtrR0 || isPtrTOS) { 1317 if (isPtrR0 && isPtrTOS) { 1318 if (op != OP_MINUS) { 1319 error("Unsupported pointer-pointer operation %d.", op); 1320 } 1321 if (! typeEqual(pR0Type, pTOSType)) { 1322 error("Incompatible pointer types for subtraction."); 1323 } 1324 o4(0xE0410000); // sub r0,r1,r0 1325 setR0Type(mkpInt); 1326 int size = sizeOf(pR0Type->pHead); 1327 if (size != 1) { 1328 pushR0(); 1329 li(size); 1330 // TODO: Optimize for power-of-two. 1331 genOp(OP_DIV); 1332 } 1333 } else { 1334 if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) { 1335 error("Unsupported pointer-scalar operation %d", op); 1336 } 1337 Type* pPtrType = getPointerArithmeticResultType( 1338 pR0Type, pTOSType); 1339 int size = sizeOf(pPtrType->pHead); 1340 if (size != 1) { 1341 // TODO: Optimize for power-of-two. 1342 liReg(size, 2); 1343 if (isPtrR0) { 1344 o4(0x0E0010192); // mul r1,r2,r1 1345 } else { 1346 o4(0x0E0000092); // mul r0,r2,r0 1347 } 1348 } 1349 switch(op) { 1350 case OP_PLUS: 1351 o4(0xE0810000); // add r0,r1,r0 1352 break; 1353 case OP_MINUS: 1354 o4(0xE0410000); // sub r0,r1,r0 1355 break; 1356 } 1357 setR0Type(pPtrType); 1358 } 1359 } else { 1360 switch(op) { 1361 case OP_MUL: 1362 o4(0x0E0000091); // mul r0,r1,r0 1363 break; 1364 case OP_DIV: 1365 callRuntime((void*) runtime_DIV); 1366 break; 1367 case OP_MOD: 1368 callRuntime((void*) runtime_MOD); 1369 break; 1370 case OP_PLUS: 1371 o4(0xE0810000); // add r0,r1,r0 1372 break; 1373 case OP_MINUS: 1374 o4(0xE0410000); // sub r0,r1,r0 1375 break; 1376 case OP_SHIFT_LEFT: 1377 o4(0xE1A00011); // lsl r0,r1,r0 1378 break; 1379 case OP_SHIFT_RIGHT: 1380 o4(0xE1A00051); // asr r0,r1,r0 1381 break; 1382 case OP_BIT_AND: 1383 o4(0xE0010000); // and r0,r1,r0 1384 break; 1385 case OP_BIT_XOR: 1386 o4(0xE0210000); // eor r0,r1,r0 1387 break; 1388 case OP_BIT_OR: 1389 o4(0xE1810000); // orr r0,r1,r0 1390 break; 1391 case OP_BIT_NOT: 1392 o4(0xE1E00000); // mvn r0, r0 1393 break; 1394 default: 1395 error("Unimplemented op %d\n", op); 1396 break; 1397 } 1398 } 1399 } else { 1400 Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType; 1401 if (pResultType->tag == TY_DOUBLE) { 1402 setupDoubleArgs(); 1403 1404 switch(op) { 1405 case OP_MUL: 1406 #ifdef ARM_USE_VFP 1407 o4(0xEE267B07); // fmuld d7, d6, d7 1408 #else 1409 callRuntime((void*) runtime_op_mul_dd); 1410 #endif 1411 break; 1412 case OP_DIV: 1413 #ifdef ARM_USE_VFP 1414 o4(0xEE867B07); // fdivd d7, d6, d7 1415 #else 1416 callRuntime((void*) runtime_op_div_dd); 1417 #endif 1418 break; 1419 case OP_PLUS: 1420 #ifdef ARM_USE_VFP 1421 o4(0xEE367B07); // faddd d7, d6, d7 1422 #else 1423 callRuntime((void*) runtime_op_add_dd); 1424 #endif 1425 break; 1426 case OP_MINUS: 1427 #ifdef ARM_USE_VFP 1428 o4(0xEE367B47); // fsubd d7, d6, d7 1429 #else 1430 callRuntime((void*) runtime_op_sub_dd); 1431 #endif 1432 break; 1433 default: 1434 error("Unsupported binary floating operation %d\n", op); 1435 break; 1436 } 1437 } else { 1438 setupFloatArgs(); 1439 switch(op) { 1440 case OP_MUL: 1441 #ifdef ARM_USE_VFP 1442 o4(0xEE677A27); // fmuls s15, s14, s15 1443 #else 1444 callRuntime((void*) runtime_op_mul_ff); 1445 #endif 1446 break; 1447 case OP_DIV: 1448 #ifdef ARM_USE_VFP 1449 o4(0xEEC77A27); // fdivs s15, s14, s15 1450 #else 1451 callRuntime((void*) runtime_op_div_ff); 1452 #endif 1453 break; 1454 case OP_PLUS: 1455 #ifdef ARM_USE_VFP 1456 o4(0xEE777A27); // fadds s15, s14, s15 1457 #else 1458 callRuntime((void*) runtime_op_add_ff); 1459 #endif 1460 break; 1461 case OP_MINUS: 1462 #ifdef ARM_USE_VFP 1463 o4(0xEE777A67); // fsubs s15, s14, s15 1464 #else 1465 callRuntime((void*) runtime_op_sub_ff); 1466 #endif 1467 break; 1468 default: 1469 error("Unsupported binary floating operation %d\n", op); 1470 break; 1471 } 1472 } 1473 setR0Type(pResultType); 1474 } 1475 } 1476 1477 virtual void gUnaryCmp(int op) { 1478 if (op != OP_LOGICAL_NOT) { 1479 error("Unknown unary cmp %d", op); 1480 } else { 1481 Type* pR0Type = getR0Type(); 1482 TypeTag tag = collapseType(pR0Type->tag); 1483 switch(tag) { 1484 case TY_INT: 1485 o4(0xE3A01000); // mov r1, #0 1486 o4(0xE1510000); // cmp r1, r0 1487 o4(0x03A00001); // moveq r0,#1 1488 o4(0x13A00000); // movne r0,#0 1489 break; 1490 case TY_FLOAT: 1491 #ifdef ARM_USE_VFP 1492 o4(0xEEF57A40); // fcmpzs s15 1493 o4(0xEEF1FA10); // fmstat 1494 o4(0x03A00001); // moveq r0,#1 1495 o4(0x13A00000); // movne r0,#0 1496 #else 1497 callRuntime((void*) runtime_is_zero_f); 1498 #endif 1499 break; 1500 case TY_DOUBLE: 1501 #ifdef ARM_USE_VFP 1502 o4(0xEEB57B40); // fcmpzd d7 1503 o4(0xEEF1FA10); // fmstat 1504 o4(0x03A00001); // moveq r0,#1 1505 o4(0x13A00000); // movne r0,#0 1506 #else 1507 callRuntime((void*) runtime_is_zero_d); 1508 #endif 1509 break; 1510 default: 1511 error("gUnaryCmp unsupported type"); 1512 break; 1513 } 1514 } 1515 setR0Type(mkpInt); 1516 } 1517 1518 virtual void genUnaryOp(int op) { 1519 Type* pR0Type = getR0Type(); 1520 TypeTag tag = collapseType(pR0Type->tag); 1521 switch(tag) { 1522 case TY_INT: 1523 switch(op) { 1524 case OP_MINUS: 1525 o4(0xE3A01000); // mov r1, #0 1526 o4(0xE0410000); // sub r0,r1,r0 1527 break; 1528 case OP_BIT_NOT: 1529 o4(0xE1E00000); // mvn r0, r0 1530 break; 1531 default: 1532 error("Unknown unary op %d\n", op); 1533 break; 1534 } 1535 break; 1536 case TY_FLOAT: 1537 case TY_DOUBLE: 1538 switch (op) { 1539 case OP_MINUS: 1540 if (tag == TY_FLOAT) { 1541 #ifdef ARM_USE_VFP 1542 o4(0xEEF17A67); // fnegs s15, s15 1543 #else 1544 callRuntime((void*) runtime_op_neg_f); 1545 #endif 1546 } else { 1547 #ifdef ARM_USE_VFP 1548 o4(0xEEB17B47); // fnegd d7, d7 1549 #else 1550 callRuntime((void*) runtime_op_neg_d); 1551 #endif 1552 } 1553 break; 1554 case OP_BIT_NOT: 1555 error("Can't apply '~' operator to a float or double."); 1556 break; 1557 default: 1558 error("Unknown unary op %d\n", op); 1559 break; 1560 } 1561 break; 1562 default: 1563 error("genUnaryOp unsupported type"); 1564 break; 1565 } 1566 } 1567 1568 virtual void pushR0() { 1569 Type* pR0Type = getR0Type(); 1570 TypeTag r0ct = collapseType(pR0Type->tag); 1571 1572 #ifdef ARM_USE_VFP 1573 switch (r0ct ) { 1574 case TY_FLOAT: 1575 o4(0xED6D7A01); // fstmfds sp!,{s15} 1576 mStackUse += 4; 1577 break; 1578 case TY_DOUBLE: 1579 o4(0xED2D7B02); // fstmfdd sp!,{d7} 1580 mStackUse += 8; 1581 break; 1582 default: 1583 o4(0xE92D0001); // stmfd sp!,{r0} 1584 mStackUse += 4; 1585 } 1586 #else 1587 1588 if (r0ct != TY_DOUBLE) { 1589 o4(0xE92D0001); // stmfd sp!,{r0} 1590 mStackUse += 4; 1591 } else { 1592 o4(0xE92D0003); // stmfd sp!,{r0,r1} 1593 mStackUse += 8; 1594 } 1595 #endif 1596 pushType(); 1597 LOG_STACK("pushR0: %d\n", mStackUse); 1598 } 1599 1600 virtual void over() { 1601 // We know it's only used for int-ptr ops (++/--) 1602 1603 Type* pR0Type = getR0Type(); 1604 TypeTag r0ct = collapseType(pR0Type->tag); 1605 1606 Type* pTOSType = getTOSType(); 1607 TypeTag tosct = collapseType(pTOSType->tag); 1608 1609 assert (r0ct == TY_INT && tosct == TY_INT); 1610 1611 o4(0xE8BD0002); // ldmfd sp!,{r1} 1612 o4(0xE92D0001); // stmfd sp!,{r0} 1613 o4(0xE92D0002); // stmfd sp!,{r1} 1614 overType(); 1615 mStackUse += 4; 1616 } 1617 1618 virtual void popR0() { 1619 Type* pTOSType = getTOSType(); 1620 TypeTag tosct = collapseType(pTOSType->tag); 1621 #ifdef ARM_USE_VFP 1622 if (tosct == TY_FLOAT || tosct == TY_DOUBLE) { 1623 error("Unsupported popR0 float/double"); 1624 } 1625 #endif 1626 switch (tosct){ 1627 case TY_INT: 1628 case TY_FLOAT: 1629 o4(0xE8BD0001); // ldmfd sp!,{r0} 1630 mStackUse -= 4; 1631 break; 1632 case TY_DOUBLE: 1633 o4(0xE8BD0003); // ldmfd sp!,{r0, r1} // Restore R0 1634 mStackUse -= 8; 1635 break; 1636 default: 1637 error("Can't pop this type."); 1638 break; 1639 } 1640 popType(); 1641 LOG_STACK("popR0: %d\n", mStackUse); 1642 } 1643 1644 virtual void storeR0ToTOS() { 1645 Type* pPointerType = getTOSType(); 1646 assert(pPointerType->tag == TY_POINTER); 1647 Type* pDestType = pPointerType->pHead; 1648 convertR0(pDestType); 1649 o4(0xE8BD0004); // ldmfd sp!,{r2} 1650 popType(); 1651 mStackUse -= 4; 1652 switch (pDestType->tag) { 1653 case TY_POINTER: 1654 case TY_INT: 1655 o4(0xE5820000); // str r0, [r2] 1656 break; 1657 case TY_FLOAT: 1658 #ifdef ARM_USE_VFP 1659 o4(0xEDC27A00); // fsts s15, [r2, #0] 1660 #else 1661 o4(0xE5820000); // str r0, [r2] 1662 #endif 1663 break; 1664 case TY_SHORT: 1665 o4(0xE1C200B0); // strh r0, [r2] 1666 break; 1667 case TY_CHAR: 1668 o4(0xE5C20000); // strb r0, [r2] 1669 break; 1670 case TY_DOUBLE: 1671 #ifdef ARM_USE_VFP 1672 o4(0xED827B00); // fstd d7, [r2, #0] 1673 #else 1674 o4(0xE1C200F0); // strd r0, [r2] 1675 #endif 1676 break; 1677 case TY_STRUCT: 1678 { 1679 int size = sizeOf(pDestType); 1680 if (size > 0) { 1681 liReg(size, 1); 1682 callRuntime((void*) runtime_structCopy); 1683 } 1684 } 1685 break; 1686 default: 1687 error("storeR0ToTOS: unimplemented type %d", 1688 pDestType->tag); 1689 break; 1690 } 1691 setR0Type(pDestType); 1692 } 1693 1694 virtual void loadR0FromR0() { 1695 Type* pPointerType = getR0Type(); 1696 assert(pPointerType->tag == TY_POINTER); 1697 Type* pNewType = pPointerType->pHead; 1698 TypeTag tag = pNewType->tag; 1699 switch (tag) { 1700 case TY_POINTER: 1701 case TY_INT: 1702 o4(0xE5900000); // ldr r0, [r0] 1703 break; 1704 case TY_FLOAT: 1705 #ifdef ARM_USE_VFP 1706 o4(0xEDD07A00); // flds s15, [r0, #0] 1707 #else 1708 o4(0xE5900000); // ldr r0, [r0] 1709 #endif 1710 break; 1711 case TY_SHORT: 1712 o4(0xE1D000F0); // ldrsh r0, [r0] 1713 break; 1714 case TY_CHAR: 1715 o4(0xE5D00000); // ldrb r0, [r0] 1716 break; 1717 case TY_DOUBLE: 1718 #ifdef ARM_USE_VFP 1719 o4(0xED907B00); // fldd d7, [r0, #0] 1720 #else 1721 o4(0xE1C000D0); // ldrd r0, [r0] 1722 #endif 1723 break; 1724 case TY_ARRAY: 1725 pNewType = pNewType->pTail; 1726 break; 1727 case TY_STRUCT: 1728 break; 1729 default: 1730 error("loadR0FromR0: unimplemented type %d", tag); 1731 break; 1732 } 1733 setR0Type(pNewType); 1734 } 1735 1736 virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) { 1737 if (ea > -LOCAL && ea < LOCAL) { 1738 // Local, fp relative 1739 1740 size_t immediate = 0; 1741 bool inRange = false; 1742 if (ea < 0) { 1743 inRange = encode12BitImmediate(-ea, &immediate); 1744 o4(0xE24B0000 | immediate); // sub r0, fp, #ea 1745 } else { 1746 inRange = encode12BitImmediate(ea, &immediate); 1747 o4(0xE28B0000 | immediate); // add r0, fp, #ea 1748 } 1749 if (! inRange) { 1750 error("Offset out of range: %08x", ea); 1751 } 1752 } else { 1753 // Global, absolute. 1754 o4(0xE59F0000); // ldr r0, .L1 1755 o4(0xEA000000); // b .L99 1756 o4(ea); // .L1: .word 0 1757 // .L99: 1758 } 1759 setR0Type(pPointerType, et); 1760 } 1761 1762 virtual int leaForward(int ea, Type* pPointerType) { 1763 setR0Type(pPointerType); 1764 int result = ea; 1765 int pc = getPC(); 1766 int offset = 0; 1767 if (ea) { 1768 offset = (pc - ea - 8) >> 2; 1769 if ((offset & 0xffff) != offset) { 1770 error("function forward reference out of bounds"); 1771 } 1772 } else { 1773 offset = 0; 1774 } 1775 o4(0xE59F0000 | offset); // ldr r0, .L1 1776 1777 if (ea == 0) { 1778 o4(0xEA000000); // b .L99 1779 result = getPC(); 1780 o4(ea); // .L1: .word 0 1781 // .L99: 1782 } 1783 return result; 1784 } 1785 1786 virtual void convertR0Imp(Type* pType, bool isCast){ 1787 Type* pR0Type = getR0Type(); 1788 if (isPointerType(pType) && isPointerType(pR0Type)) { 1789 Type* pA = pR0Type; 1790 Type* pB = pType; 1791 // Array decays to pointer 1792 if (pA->tag == TY_ARRAY && pB->tag == TY_POINTER) { 1793 pA = pA->pTail; 1794 } 1795 if (! (typeEqual(pA, pB) 1796 || pB->pHead->tag == TY_VOID 1797 || (pA->tag == TY_POINTER && pB->tag == TY_POINTER && isCast) 1798 )) { 1799 error("Incompatible pointer or array types"); 1800 } 1801 } else if (bitsSame(pType, pR0Type)) { 1802 // do nothing special 1803 } else { 1804 TypeTag r0Tag = collapseType(pR0Type->tag); 1805 TypeTag destTag = collapseType(pType->tag); 1806 if (r0Tag == TY_INT) { 1807 if (destTag == TY_FLOAT) { 1808 #ifdef ARM_USE_VFP 1809 o4(0xEE070A90); // fmsr s15, r0 1810 o4(0xEEF87AE7); // fsitos s15, s15 1811 1812 #else 1813 callRuntime((void*) runtime_int_to_float); 1814 #endif 1815 } else { 1816 assert(destTag == TY_DOUBLE); 1817 #ifdef ARM_USE_VFP 1818 o4(0xEE070A90); // fmsr s15, r0 1819 o4(0xEEB87BE7); // fsitod d7, s15 1820 1821 #else 1822 callRuntime((void*) runtime_int_to_double); 1823 #endif 1824 } 1825 } else if (r0Tag == TY_FLOAT) { 1826 if (destTag == TY_INT) { 1827 #ifdef ARM_USE_VFP 1828 o4(0xEEFD7AE7); // ftosizs s15, s15 1829 o4(0xEE170A90); // fmrs r0, s15 1830 #else 1831 callRuntime((void*) runtime_float_to_int); 1832 #endif 1833 } else { 1834 assert(destTag == TY_DOUBLE); 1835 #ifdef ARM_USE_VFP 1836 o4(0xEEB77AE7); // fcvtds d7, s15 1837 #else 1838 callRuntime((void*) runtime_float_to_double); 1839 #endif 1840 } 1841 } else { 1842 if (r0Tag == TY_DOUBLE) { 1843 if (destTag == TY_INT) { 1844 #ifdef ARM_USE_VFP 1845 o4(0xEEFD7BC7); // ftosizd s15, d7 1846 o4(0xEE170A90); // fmrs r0, s15 1847 #else 1848 callRuntime((void*) runtime_double_to_int); 1849 #endif 1850 } else { 1851 if(destTag == TY_FLOAT) { 1852 #ifdef ARM_USE_VFP 1853 o4(0xEEF77BC7); // fcvtsd s15, d7 1854 #else 1855 callRuntime((void*) runtime_double_to_float); 1856 #endif 1857 } else { 1858 incompatibleTypes(pR0Type, pType); 1859 } 1860 } 1861 } else { 1862 incompatibleTypes(pR0Type, pType); 1863 } 1864 } 1865 } 1866 setR0Type(pType); 1867 } 1868 1869 virtual int beginFunctionCallArguments() { 1870 int pc = getPC(); 1871 o4(0xE24DDF00); // Placeholder sub sp, sp, #0 1872 return pc; 1873 } 1874 1875 virtual size_t storeR0ToArg(int l, Type* pArgType) { 1876 convertR0(pArgType); 1877 Type* pR0Type = getR0Type(); 1878 TypeTag r0ct = collapseType(pR0Type->tag); 1879 #ifdef ARM_USE_VFP 1880 switch(r0ct) { 1881 case TY_INT: 1882 if (l < 0 || l > 4096-4) { 1883 error("l out of range for stack offset: 0x%08x", l); 1884 } 1885 o4(0xE58D0000 | l); // str r0, [sp, #l] 1886 return 4; 1887 case TY_FLOAT: 1888 if (l < 0 || l > 1020 || (l & 3)) { 1889 error("l out of range for stack offset: 0x%08x", l); 1890 } 1891 o4(0xEDCD7A00 | (l >> 2)); // fsts s15, [sp, #l] 1892 return 4; 1893 case TY_DOUBLE: { 1894 // Align to 8 byte boundary 1895 int l2 = (l + 7) & ~7; 1896 if (l2 < 0 || l2 > 1020 || (l2 & 3)) { 1897 error("l out of range for stack offset: 0x%08x", l); 1898 } 1899 o4(0xED8D7B00 | (l2 >> 2)); // fstd d7, [sp, #l2] 1900 return (l2 - l) + 8; 1901 } 1902 default: 1903 assert(false); 1904 return 0; 1905 } 1906 #else 1907 switch(r0ct) { 1908 case TY_INT: 1909 case TY_FLOAT: 1910 if (l < 0 || l > 4096-4) { 1911 error("l out of range for stack offset: 0x%08x", l); 1912 } 1913 o4(0xE58D0000 + l); // str r0, [sp, #l] 1914 return 4; 1915 case TY_DOUBLE: { 1916 // Align to 8 byte boundary 1917 int l2 = (l + 7) & ~7; 1918 if (l2 < 0 || l2 > 4096-8) { 1919 error("l out of range for stack offset: 0x%08x", l); 1920 } 1921 o4(0xE58D0000 + l2); // str r0, [sp, #l] 1922 o4(0xE58D1000 + l2 + 4); // str r1, [sp, #l+4] 1923 return (l2 - l) + 8; 1924 } 1925 default: 1926 assert(false); 1927 return 0; 1928 } 1929 #endif 1930 } 1931 1932 virtual void endFunctionCallArguments(Type* pDecl, int a, int l) { 1933 int argumentStackUse = l; 1934 // Have to calculate register arg count from actual stack size, 1935 // in order to properly handle ... functions. 1936 int regArgCount = l >> 2; 1937 if (regArgCount > 4) { 1938 regArgCount = 4; 1939 } 1940 if (regArgCount > 0) { 1941 argumentStackUse -= regArgCount * 4; 1942 o4(0xE8BD0000 | ((1 << regArgCount) - 1)); // ldmfd sp!,{} 1943 } 1944 mStackUse += argumentStackUse; 1945 1946 // Align stack. 1947 int missalignment = mStackUse - ((mStackUse / STACK_ALIGNMENT) 1948 * STACK_ALIGNMENT); 1949 mStackAlignmentAdjustment = 0; 1950 if (missalignment > 0) { 1951 mStackAlignmentAdjustment = STACK_ALIGNMENT - missalignment; 1952 } 1953 l += mStackAlignmentAdjustment; 1954 1955 if (l < 0 || l > 0x3FC) { 1956 error("L out of range for stack adjustment: 0x%08x", l); 1957 } 1958 flush(); 1959 * (int*) a = 0xE24DDF00 | (l >> 2); // sub sp, sp, #0 << 2 1960 mStackUse += mStackAlignmentAdjustment; 1961 LOG_STACK("endFunctionCallArguments mStackUse: %d, mStackAlignmentAdjustment %d\n", 1962 mStackUse, mStackAlignmentAdjustment); 1963 } 1964 1965 virtual int callForward(int symbol, Type* pFunc) { 1966 setR0Type(pFunc->pHead); 1967 // Forward calls are always short (local) 1968 int pc = getPC(); 1969 o4(0xEB000000 | encodeAddress(symbol)); 1970 return pc; 1971 } 1972 1973 virtual void callIndirect(int l, Type* pFunc) { 1974 assert(pFunc->tag == TY_FUNC); 1975 popType(); // Get rid of indirect fn pointer type 1976 int argCount = l >> 2; 1977 int poppedArgs = argCount > 4 ? 4 : argCount; 1978 int adjustedL = l - (poppedArgs << 2) + mStackAlignmentAdjustment; 1979 if (adjustedL < 0 || adjustedL > 4096-4) { 1980 error("l out of range for stack offset: 0x%08x", l); 1981 } 1982 o4(0xE59DC000 | (0xfff & adjustedL)); // ldr r12, [sp,#adjustedL] 1983 o4(0xE12FFF3C); // blx r12 1984 Type* pReturnType = pFunc->pHead; 1985 setR0Type(pReturnType); 1986 #ifdef ARM_USE_VFP 1987 switch(pReturnType->tag) { 1988 case TY_FLOAT: 1989 o4(0xEE070A90); // fmsr s15, r0 1990 break; 1991 case TY_DOUBLE: 1992 o4(0xEC410B17); // fmdrr d7, r0, r1 1993 break; 1994 default: 1995 break; 1996 } 1997 #endif 1998 } 1999 2000 virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) { 2001 int argCount = l >> 2; 2002 // Have to calculate register arg count from actual stack size, 2003 // in order to properly handle ... functions. 2004 int regArgCount = l >> 2; 2005 if (regArgCount > 4) { 2006 regArgCount = 4; 2007 } 2008 int stackArgs = argCount - regArgCount; 2009 int stackUse = stackArgs + (isIndirect ? 1 : 0) 2010 + (mStackAlignmentAdjustment >> 2); 2011 if (stackUse) { 2012 if (stackUse < 0 || stackUse > 255) { 2013 error("L out of range for stack adjustment: 0x%08x", l); 2014 } 2015 o4(0xE28DDF00 | stackUse); // add sp, sp, #stackUse << 2 2016 mStackUse -= stackUse * 4; 2017 LOG_STACK("adjustStackAfterCall: %d\n", mStackUse); 2018 } 2019 } 2020 2021 virtual int jumpOffset() { 2022 return 8; 2023 } 2024 2025 /* output a symbol and patch all calls to it */ 2026 virtual void gsym(int t) { 2027 int n; 2028 int base = getBase(); 2029 int pc = getPC(); 2030 while (t) { 2031 int data = * (int*) t; 2032 int decodedOffset = ((BRANCH_REL_ADDRESS_MASK & data) << 2); 2033 if (decodedOffset == 0) { 2034 n = 0; 2035 } else { 2036 n = base + decodedOffset; /* next value */ 2037 } 2038 *(int *) t = (data & ~BRANCH_REL_ADDRESS_MASK) 2039 | encodeRelAddress(pc - t - 8); 2040 t = n; 2041 } 2042 } 2043 2044 /* output a symbol and patch all calls to it */ 2045 virtual void resolveForward(int t) { 2046 if (t) { 2047 int pc = getPC(); 2048 *(int *) t = pc; 2049 } 2050 } 2051 2052 virtual int finishCompile() { 2053 #if defined(__arm__) 2054 const long base = long(getBase()); 2055 const long curr = long(getPC()); 2056 int err = cacheflush(base, curr, 0); 2057 return err; 2058 #else 2059 return 0; 2060 #endif 2061 } 2062 2063 /** 2064 * alignment (in bytes) for this type of data 2065 */ 2066 virtual size_t alignmentOf(Type* pType){ 2067 switch(pType->tag) { 2068 case TY_CHAR: 2069 return 1; 2070 case TY_SHORT: 2071 return 2; 2072 case TY_DOUBLE: 2073 return 8; 2074 case TY_ARRAY: 2075 return alignmentOf(pType->pHead); 2076 case TY_STRUCT: 2077 return pType->pHead->alignment & 0x7fffffff; 2078 case TY_FUNC: 2079 error("alignment of func not supported"); 2080 return 1; 2081 default: 2082 return 4; 2083 } 2084 } 2085 2086 /** 2087 * Array element alignment (in bytes) for this type of data. 2088 */ 2089 virtual size_t sizeOf(Type* pType){ 2090 switch(pType->tag) { 2091 case TY_INT: 2092 return 4; 2093 case TY_SHORT: 2094 return 2; 2095 case TY_CHAR: 2096 return 1; 2097 case TY_FLOAT: 2098 return 4; 2099 case TY_DOUBLE: 2100 return 8; 2101 case TY_POINTER: 2102 return 4; 2103 case TY_ARRAY: 2104 return pType->length * sizeOf(pType->pHead); 2105 case TY_STRUCT: 2106 return pType->pHead->length; 2107 default: 2108 error("Unsupported type %d", pType->tag); 2109 return 0; 2110 } 2111 } 2112 2113 private: 2114 2115 static const int BRANCH_REL_ADDRESS_MASK = 0x00ffffff; 2116 2117 /** Encode a relative address that might also be 2118 * a label. 2119 */ 2120 int encodeAddress(int value) { 2121 int base = getBase(); 2122 if (value >= base && value <= getPC() ) { 2123 // This is a label, encode it relative to the base. 2124 value = value - base; 2125 } 2126 return encodeRelAddress(value); 2127 } 2128 2129 int encodeRelAddress(int value) { 2130 return BRANCH_REL_ADDRESS_MASK & (value >> 2); 2131 } 2132 2133 int calcRegArgCount(Type* pDecl) { 2134 int reg = 0; 2135 Type* pArgs = pDecl->pTail; 2136 while (pArgs && reg < 4) { 2137 Type* pArg = pArgs->pHead; 2138 if ( pArg->tag == TY_DOUBLE) { 2139 int evenReg = (reg + 1) & ~1; 2140 if (evenReg >= 4) { 2141 break; 2142 } 2143 reg = evenReg + 2; 2144 } else { 2145 reg++; 2146 } 2147 pArgs = pArgs->pTail; 2148 } 2149 return reg; 2150 } 2151 2152 void setupIntPtrArgs() { 2153 o4(0xE8BD0002); // ldmfd sp!,{r1} 2154 mStackUse -= 4; 2155 popType(); 2156 } 2157 2158 /* Pop TOS to R1 (use s14 if VFP) 2159 * Make sure both R0 and TOS are floats. (Could be ints) 2160 * We know that at least one of R0 and TOS is already a float 2161 */ 2162 void setupFloatArgs() { 2163 Type* pR0Type = getR0Type(); 2164 Type* pTOSType = getTOSType(); 2165 TypeTag tagR0 = collapseType(pR0Type->tag); 2166 TypeTag tagTOS = collapseType(pTOSType->tag); 2167 if (tagR0 != TY_FLOAT) { 2168 assert(tagR0 == TY_INT); 2169 #ifdef ARM_USE_VFP 2170 o4(0xEE070A90); // fmsr s15, r0 2171 o4(0xEEF87AE7); // fsitos s15, s15 2172 #else 2173 callRuntime((void*) runtime_int_to_float); 2174 #endif 2175 } 2176 if (tagTOS != TY_FLOAT) { 2177 assert(tagTOS == TY_INT); 2178 assert(tagR0 == TY_FLOAT); 2179 #ifdef ARM_USE_VFP 2180 o4(0xECBD7A01); // fldmfds sp!, {s14} 2181 o4(0xEEB87AC7); // fsitos s14, s14 2182 #else 2183 o4(0xE92D0001); // stmfd sp!,{r0} // push R0 2184 o4(0xE59D0004); // ldr r0, [sp, #4] 2185 callRuntime((void*) runtime_int_to_float); 2186 o4(0xE1A01000); // mov r1, r0 2187 o4(0xE8BD0001); // ldmfd sp!,{r0} // pop R0 2188 o4(0xE28DD004); // add sp, sp, #4 // Pop sp 2189 #endif 2190 } else { 2191 // Pop TOS 2192 #ifdef ARM_USE_VFP 2193 o4(0xECBD7A01); // fldmfds sp!, {s14} 2194 2195 #else 2196 o4(0xE8BD0002); // ldmfd sp!,{r1} 2197 #endif 2198 } 2199 mStackUse -= 4; 2200 popType(); 2201 } 2202 2203 /* Pop TOS into R2..R3 (use D6 if VFP) 2204 * Make sure both R0 and TOS are doubles. Could be floats or ints. 2205 * We know that at least one of R0 and TOS are already a double. 2206 */ 2207 2208 void setupDoubleArgs() { 2209 Type* pR0Type = getR0Type(); 2210 Type* pTOSType = getTOSType(); 2211 TypeTag tagR0 = collapseType(pR0Type->tag); 2212 TypeTag tagTOS = collapseType(pTOSType->tag); 2213 if (tagR0 != TY_DOUBLE) { 2214 if (tagR0 == TY_INT) { 2215 #ifdef ARM_USE_VFP 2216 o4(0xEE070A90); // fmsr s15, r0 2217 o4(0xEEB87BE7); // fsitod d7, s15 2218 2219 #else 2220 callRuntime((void*) runtime_int_to_double); 2221 #endif 2222 } else { 2223 assert(tagR0 == TY_FLOAT); 2224 #ifdef ARM_USE_VFP 2225 o4(0xEEB77AE7); // fcvtds d7, s15 2226 #else 2227 callRuntime((void*) runtime_float_to_double); 2228 #endif 2229 } 2230 } 2231 if (tagTOS != TY_DOUBLE) { 2232 #ifdef ARM_USE_VFP 2233 if (tagTOS == TY_INT) { 2234 o4(0xECFD6A01); // fldmfds sp!,{s13} 2235 o4(0xEEB86BE6); // fsitod d6, s13 2236 } else { 2237 assert(tagTOS == TY_FLOAT); 2238 o4(0xECFD6A01); // fldmfds sp!,{s13} 2239 o4(0xEEB76AE6); // fcvtds d6, s13 2240 } 2241 #else 2242 o4(0xE92D0003); // stmfd sp!,{r0,r1} // push r0,r1 2243 o4(0xE59D0008); // ldr r0, [sp, #8] 2244 if (tagTOS == TY_INT) { 2245 callRuntime((void*) runtime_int_to_double); 2246 } else { 2247 assert(tagTOS == TY_FLOAT); 2248 callRuntime((void*) runtime_float_to_double); 2249 } 2250 o4(0xE1A02000); // mov r2, r0 2251 o4(0xE1A03001); // mov r3, r1 2252 o4(0xE8BD0003); // ldmfd sp!,{r0, r1} // Restore R0 2253 o4(0xE28DD004); // add sp, sp, #4 // Pop sp 2254 #endif 2255 mStackUse -= 4; 2256 } else { 2257 #ifdef ARM_USE_VFP 2258 o4(0xECBD6B02); // fldmfdd sp!, {d6} 2259 #else 2260 o4(0xE8BD000C); // ldmfd sp!,{r2,r3} 2261 #endif 2262 mStackUse -= 8; 2263 } 2264 popType(); 2265 } 2266 2267 void liReg(int t, int reg) { 2268 assert(reg >= 0 && reg < 16); 2269 int rN = (reg & 0xf) << 12; 2270 size_t encodedImmediate; 2271 if (encode12BitImmediate(t, &encodedImmediate)) { 2272 o4(0xE3A00000 | encodedImmediate | rN); // mov rN, #0 2273 } else if (encode12BitImmediate(-(t+1), &encodedImmediate)) { 2274 // mvn means move constant ^ ~0 2275 o4(0xE3E00000 | encodedImmediate | rN); // mvn rN, #0 2276 } else { 2277 o4(0xE51F0000 | rN); // ldr rN, .L3 2278 o4(0xEA000000); // b .L99 2279 o4(t); // .L3: .word 0 2280 // .L99: 2281 } 2282 } 2283 2284 void incompatibleTypes(Type* pR0Type, Type* pType) { 2285 error("Incompatible types old: %d new: %d", pR0Type->tag, pType->tag); 2286 } 2287 2288 void callRuntime(void* fn) { 2289 o4(0xE59FC000); // ldr r12, .L1 2290 o4(0xEA000000); // b .L99 2291 o4((int) fn); //.L1: .word fn 2292 o4(0xE12FFF3C); //.L99: blx r12 2293 } 2294 2295 // Integer math: 2296 2297 static int runtime_DIV(int b, int a) { 2298 return a / b; 2299 } 2300 2301 static int runtime_MOD(int b, int a) { 2302 return a % b; 2303 } 2304 2305 static void runtime_structCopy(void* src, size_t size, void* dest) { 2306 memcpy(dest, src, size); 2307 } 2308 2309 #ifndef ARM_USE_VFP 2310 2311 // Comparison to zero 2312 2313 static int runtime_is_non_zero_f(float a) { 2314 return a != 0; 2315 } 2316 2317 static int runtime_is_non_zero_d(double a) { 2318 return a != 0; 2319 } 2320 2321 // Comparison to zero 2322 2323 static int runtime_is_zero_f(float a) { 2324 return a == 0; 2325 } 2326 2327 static int runtime_is_zero_d(double a) { 2328 return a == 0; 2329 } 2330 2331 // Type conversion 2332 2333 static int runtime_float_to_int(float a) { 2334 return (int) a; 2335 } 2336 2337 static double runtime_float_to_double(float a) { 2338 return (double) a; 2339 } 2340 2341 static int runtime_double_to_int(double a) { 2342 return (int) a; 2343 } 2344 2345 static float runtime_double_to_float(double a) { 2346 return (float) a; 2347 } 2348 2349 static float runtime_int_to_float(int a) { 2350 return (float) a; 2351 } 2352 2353 static double runtime_int_to_double(int a) { 2354 return (double) a; 2355 } 2356 2357 // Comparisons float 2358 2359 static int runtime_cmp_eq_ff(float b, float a) { 2360 return a == b; 2361 } 2362 2363 static int runtime_cmp_ne_ff(float b, float a) { 2364 return a != b; 2365 } 2366 2367 static int runtime_cmp_lt_ff(float b, float a) { 2368 return a < b; 2369 } 2370 2371 static int runtime_cmp_le_ff(float b, float a) { 2372 return a <= b; 2373 } 2374 2375 static int runtime_cmp_ge_ff(float b, float a) { 2376 return a >= b; 2377 } 2378 2379 static int runtime_cmp_gt_ff(float b, float a) { 2380 return a > b; 2381 } 2382 2383 // Comparisons double 2384 2385 static int runtime_cmp_eq_dd(double b, double a) { 2386 return a == b; 2387 } 2388 2389 static int runtime_cmp_ne_dd(double b, double a) { 2390 return a != b; 2391 } 2392 2393 static int runtime_cmp_lt_dd(double b, double a) { 2394 return a < b; 2395 } 2396 2397 static int runtime_cmp_le_dd(double b, double a) { 2398 return a <= b; 2399 } 2400 2401 static int runtime_cmp_ge_dd(double b, double a) { 2402 return a >= b; 2403 } 2404 2405 static int runtime_cmp_gt_dd(double b, double a) { 2406 return a > b; 2407 } 2408 2409 // Math float 2410 2411 static float runtime_op_add_ff(float b, float a) { 2412 return a + b; 2413 } 2414 2415 static float runtime_op_sub_ff(float b, float a) { 2416 return a - b; 2417 } 2418 2419 static float runtime_op_mul_ff(float b, float a) { 2420 return a * b; 2421 } 2422 2423 static float runtime_op_div_ff(float b, float a) { 2424 return a / b; 2425 } 2426 2427 static float runtime_op_neg_f(float a) { 2428 return -a; 2429 } 2430 2431 // Math double 2432 2433 static double runtime_op_add_dd(double b, double a) { 2434 return a + b; 2435 } 2436 2437 static double runtime_op_sub_dd(double b, double a) { 2438 return a - b; 2439 } 2440 2441 static double runtime_op_mul_dd(double b, double a) { 2442 return a * b; 2443 } 2444 2445 static double runtime_op_div_dd(double b, double a) { 2446 return a / b; 2447 } 2448 2449 static double runtime_op_neg_d(double a) { 2450 return -a; 2451 } 2452 2453 #endif 2454 2455 static const int STACK_ALIGNMENT = 8; 2456 int mStackUse; 2457 // This variable holds the amount we adjusted the stack in the most 2458 // recent endFunctionCallArguments call. It's examined by the 2459 // following adjustStackAfterCall call. 2460 int mStackAlignmentAdjustment; 2461 }; 2462 2463 #endif // PROVIDE_ARM_CODEGEN 2464 2465 #ifdef PROVIDE_X86_CODEGEN 2466 2467 class X86CodeGenerator : public CodeGenerator { 2468 public: 2469 X86CodeGenerator() {} 2470 virtual ~X86CodeGenerator() {} 2471 2472 /* returns address to patch with local variable size 2473 */ 2474 virtual int functionEntry(Type* pDecl) { 2475 o(0xe58955); /* push %ebp, mov %esp, %ebp */ 2476 return oad(0xec81, 0); /* sub $xxx, %esp */ 2477 } 2478 2479 virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) { 2480 o(0xc3c9); /* leave, ret */ 2481 *(int *) localVariableAddress = localVariableSize; /* save local variables */ 2482 } 2483 2484 /* load immediate value */ 2485 virtual void li(int i) { 2486 oad(0xb8, i); /* mov $xx, %eax */ 2487 setR0Type(mkpInt); 2488 } 2489 2490 virtual void loadFloat(int address, Type* pType) { 2491 setR0Type(pType); 2492 switch (pType->tag) { 2493 case TY_FLOAT: 2494 oad(0x05D9, address); // flds 2495 break; 2496 case TY_DOUBLE: 2497 oad(0x05DD, address); // fldl 2498 break; 2499 default: 2500 assert(false); 2501 break; 2502 } 2503 } 2504 2505 virtual void addStructOffsetR0(int offset, Type* pType) { 2506 if (offset) { 2507 oad(0x05, offset); // addl offset, %eax 2508 } 2509 setR0Type(pType, ET_LVALUE); 2510 } 2511 2512 virtual int gjmp(int t) { 2513 return psym(0xe9, t); 2514 } 2515 2516 /* l = 0: je, l == 1: jne */ 2517 virtual int gtst(bool l, int t) { 2518 Type* pR0Type = getR0Type(); 2519 TypeTag tagR0 = pR0Type->tag; 2520 bool isFloatR0 = isFloatTag(tagR0); 2521 if (isFloatR0) { 2522 o(0xeed9); // fldz 2523 o(0xe9da); // fucompp 2524 o(0xe0df); // fnstsw %ax 2525 o(0x9e); // sahf 2526 } else { 2527 o(0xc085); // test %eax, %eax 2528 } 2529 // Use two output statements to generate one instruction. 2530 o(0x0f); // je/jne xxx 2531 return psym(0x84 + l, t); 2532 } 2533 2534 virtual void gcmp(int op) { 2535 Type* pR0Type = getR0Type(); 2536 Type* pTOSType = getTOSType(); 2537 TypeTag tagR0 = pR0Type->tag; 2538 TypeTag tagTOS = pTOSType->tag; 2539 bool isFloatR0 = isFloatTag(tagR0); 2540 bool isFloatTOS = isFloatTag(tagTOS); 2541 if (!isFloatR0 && !isFloatTOS) { 2542 int t = decodeOp(op); 2543 o(0x59); /* pop %ecx */ 2544 o(0xc139); /* cmp %eax,%ecx */ 2545 li(0); 2546 o(0x0f); /* setxx %al */ 2547 o(t + 0x90); 2548 o(0xc0); 2549 popType(); 2550 } else { 2551 setupFloatOperands(); 2552 switch (op) { 2553 case OP_EQUALS: 2554 o(0xe9da); // fucompp 2555 o(0xe0df); // fnstsw %ax 2556 o(0x9e); // sahf 2557 o(0xc0940f); // sete %al 2558 o(0xc29b0f); // setnp %dl 2559 o(0xd021); // andl %edx, %eax 2560 break; 2561 case OP_NOT_EQUALS: 2562 o(0xe9da); // fucompp 2563 o(0xe0df); // fnstsw %ax 2564 o(0x9e); // sahf 2565 o(0xc0950f); // setne %al 2566 o(0xc29a0f); // setp %dl 2567 o(0xd009); // orl %edx, %eax 2568 break; 2569 case OP_GREATER_EQUAL: 2570 o(0xe9da); // fucompp 2571 o(0xe0df); // fnstsw %ax 2572 o(0x05c4f6); // testb $5, %ah 2573 o(0xc0940f); // sete %al 2574 break; 2575 case OP_LESS: 2576 o(0xc9d9); // fxch %st(1) 2577 o(0xe9da); // fucompp 2578 o(0xe0df); // fnstsw %ax 2579 o(0x9e); // sahf 2580 o(0xc0970f); // seta %al 2581 break; 2582 case OP_LESS_EQUAL: 2583 o(0xc9d9); // fxch %st(1) 2584 o(0xe9da); // fucompp 2585 o(0xe0df); // fnstsw %ax 2586 o(0x9e); // sahf 2587 o(0xc0930f); // setea %al 2588 break; 2589 case OP_GREATER: 2590 o(0xe9da); // fucompp 2591 o(0xe0df); // fnstsw %ax 2592 o(0x45c4f6); // testb $69, %ah 2593 o(0xc0940f); // sete %al 2594 break; 2595 default: 2596 error("Unknown comparison op"); 2597 } 2598 o(0xc0b60f); // movzbl %al, %eax 2599 } 2600 setR0Type(mkpInt); 2601 } 2602 2603 virtual void genOp(int op) { 2604 Type* pR0Type = getR0Type(); 2605 Type* pTOSType = getTOSType(); 2606 TypeTag tagR0 = pR0Type->tag; 2607 TypeTag tagTOS = pTOSType->tag; 2608 bool isFloatR0 = isFloatTag(tagR0); 2609 bool isFloatTOS = isFloatTag(tagTOS); 2610 if (!isFloatR0 && !isFloatTOS) { 2611 bool isPtrR0 = isPointerTag(tagR0); 2612 bool isPtrTOS = isPointerTag(tagTOS); 2613 if (isPtrR0 || isPtrTOS) { 2614 if (isPtrR0 && isPtrTOS) { 2615 if (op != OP_MINUS) { 2616 error("Unsupported pointer-pointer operation %d.", op); 2617 } 2618 if (! typeEqual(pR0Type, pTOSType)) { 2619 error("Incompatible pointer types for subtraction."); 2620 } 2621 o(0x59); /* pop %ecx */ 2622 o(decodeOp(op)); 2623 popType(); 2624 setR0Type(mkpInt); 2625 int size = sizeOf(pR0Type->pHead); 2626 if (size != 1) { 2627 pushR0(); 2628 li(size); 2629 // TODO: Optimize for power-of-two. 2630 genOp(OP_DIV); 2631 } 2632 } else { 2633 if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) { 2634 error("Unsupported pointer-scalar operation %d", op); 2635 } 2636 Type* pPtrType = getPointerArithmeticResultType( 2637 pR0Type, pTOSType); 2638 o(0x59); /* pop %ecx */ 2639 int size = sizeOf(pPtrType->pHead); 2640 if (size != 1) { 2641 // TODO: Optimize for power-of-two. 2642 if (isPtrR0) { 2643 oad(0xC969, size); // imull $size, %ecx 2644 } else { 2645 oad(0xC069, size); // mul $size, %eax 2646 } 2647 } 2648 o(decodeOp(op)); 2649 popType(); 2650 setR0Type(pPtrType); 2651 } 2652 } else { 2653 o(0x59); /* pop %ecx */ 2654 o(decodeOp(op)); 2655 if (op == OP_MOD) 2656 o(0x92); /* xchg %edx, %eax */ 2657 popType(); 2658 } 2659 } else { 2660 Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType; 2661 setupFloatOperands(); 2662 // Both float. x87 R0 == left hand, x87 R1 == right hand 2663 switch (op) { 2664 case OP_MUL: 2665 o(0xc9de); // fmulp 2666 break; 2667 case OP_DIV: 2668 o(0xf1de); // fdivp 2669 break; 2670 case OP_PLUS: 2671 o(0xc1de); // faddp 2672 break; 2673 case OP_MINUS: 2674 o(0xe1de); // fsubp 2675 break; 2676 default: 2677 error("Unsupported binary floating operation."); 2678 break; 2679 } 2680 setR0Type(pResultType); 2681 } 2682 } 2683 2684 virtual void gUnaryCmp(int op) { 2685 if (op != OP_LOGICAL_NOT) { 2686 error("Unknown unary cmp %d", op); 2687 } else { 2688 Type* pR0Type = getR0Type(); 2689 TypeTag tag = collapseType(pR0Type->tag); 2690 switch(tag) { 2691 case TY_INT: { 2692 oad(0xb9, 0); /* movl $0, %ecx */ 2693 int t = decodeOp(op); 2694 o(0xc139); /* cmp %eax,%ecx */ 2695 li(0); 2696 o(0x0f); /* setxx %al */ 2697 o(t + 0x90); 2698 o(0xc0); 2699 } 2700 break; 2701 case TY_FLOAT: 2702 case TY_DOUBLE: 2703 o(0xeed9); // fldz 2704 o(0xe9da); // fucompp 2705 o(0xe0df); // fnstsw %ax 2706 o(0x9e); // sahf 2707 o(0xc0950f); // setne %al 2708 o(0xc29a0f); // setp %dl 2709 o(0xd009); // orl %edx, %eax 2710 o(0xc0b60f); // movzbl %al, %eax 2711 o(0x01f083); // xorl $1, %eax 2712 break; 2713 default: 2714 error("gUnaryCmp unsupported type"); 2715 break; 2716 } 2717 } 2718 setR0Type(mkpInt); 2719 } 2720 2721 virtual void genUnaryOp(int op) { 2722 Type* pR0Type = getR0Type(); 2723 TypeTag tag = collapseType(pR0Type->tag); 2724 switch(tag) { 2725 case TY_INT: 2726 oad(0xb9, 0); /* movl $0, %ecx */ 2727 o(decodeOp(op)); 2728 break; 2729 case TY_FLOAT: 2730 case TY_DOUBLE: 2731 switch (op) { 2732 case OP_MINUS: 2733 o(0xe0d9); // fchs 2734 break; 2735 case OP_BIT_NOT: 2736 error("Can't apply '~' operator to a float or double."); 2737 break; 2738 default: 2739 error("Unknown unary op %d\n", op); 2740 break; 2741 } 2742 break; 2743 default: 2744 error("genUnaryOp unsupported type"); 2745 break; 2746 } 2747 } 2748 2749 virtual void pushR0() { 2750 Type* pR0Type = getR0Type(); 2751 TypeTag r0ct = collapseType(pR0Type->tag); 2752 switch(r0ct) { 2753 case TY_INT: 2754 o(0x50); /* push %eax */ 2755 break; 2756 case TY_FLOAT: 2757 o(0x50); /* push %eax */ 2758 o(0x241cd9); // fstps 0(%esp) 2759 break; 2760 case TY_DOUBLE: 2761 o(0x50); /* push %eax */ 2762 o(0x50); /* push %eax */ 2763 o(0x241cdd); // fstpl 0(%esp) 2764 break; 2765 default: 2766 error("pushR0 unsupported type %d", r0ct); 2767 break; 2768 } 2769 pushType(); 2770 } 2771 2772 virtual void over() { 2773 // We know it's only used for int-ptr ops (++/--) 2774 2775 Type* pR0Type = getR0Type(); 2776 TypeTag r0ct = collapseType(pR0Type->tag); 2777 2778 Type* pTOSType = getTOSType(); 2779 TypeTag tosct = collapseType(pTOSType->tag); 2780 2781 assert (r0ct == TY_INT && tosct == TY_INT); 2782 2783 o(0x59); /* pop %ecx */ 2784 o(0x50); /* push %eax */ 2785 o(0x51); /* push %ecx */ 2786 2787 overType(); 2788 } 2789 2790 virtual void popR0() { 2791 Type* pR0Type = getR0Type(); 2792 TypeTag r0ct = collapseType(pR0Type->tag); 2793 switch(r0ct) { 2794 case TY_INT: 2795 o(0x58); /* popl %eax */ 2796 break; 2797 case TY_FLOAT: 2798 o(0x2404d9); // flds (%esp) 2799 o(0x58); /* popl %eax */ 2800 break; 2801 case TY_DOUBLE: 2802 o(0x2404dd); // fldl (%esp) 2803 o(0x58); /* popl %eax */ 2804 o(0x58); /* popl %eax */ 2805 break; 2806 default: 2807 error("popR0 unsupported type %d", r0ct); 2808 break; 2809 } 2810 popType(); 2811 } 2812 2813 virtual void storeR0ToTOS() { 2814 Type* pPointerType = getTOSType(); 2815 assert(pPointerType->tag == TY_POINTER); 2816 Type* pTargetType = pPointerType->pHead; 2817 convertR0(pTargetType); 2818 o(0x59); /* pop %ecx */ 2819 popType(); 2820 switch (pTargetType->tag) { 2821 case TY_POINTER: 2822 case TY_INT: 2823 o(0x0189); /* movl %eax/%al, (%ecx) */ 2824 break; 2825 case TY_SHORT: 2826 o(0x018966); /* movw %ax, (%ecx) */ 2827 break; 2828 case TY_CHAR: 2829 o(0x0188); /* movl %eax/%al, (%ecx) */ 2830 break; 2831 case TY_FLOAT: 2832 o(0x19d9); /* fstps (%ecx) */ 2833 break; 2834 case TY_DOUBLE: 2835 o(0x19dd); /* fstpl (%ecx) */ 2836 break; 2837 case TY_STRUCT: 2838 { 2839 // TODO: use alignment information to use movsw/movsl instead of movsb 2840 int size = sizeOf(pTargetType); 2841 if (size > 0) { 2842 o(0x9c); // pushf 2843 o(0x57); // pushl %edi 2844 o(0x56); // pushl %esi 2845 o(0xcf89); // movl %ecx, %edi 2846 o(0xc689); // movl %eax, %esi 2847 oad(0xb9, size); // mov #size, %ecx 2848 o(0xfc); // cld 2849 o(0xf3); // rep 2850 o(0xa4); // movsb 2851 o(0x5e); // popl %esi 2852 o(0x5f); // popl %edi 2853 o(0x9d); // popf 2854 } 2855 } 2856 break; 2857 default: 2858 error("storeR0ToTOS: unsupported type %d", 2859 pTargetType->tag); 2860 break; 2861 } 2862 setR0Type(pTargetType); 2863 } 2864 2865 virtual void loadR0FromR0() { 2866 Type* pPointerType = getR0Type(); 2867 assert(pPointerType->tag == TY_POINTER); 2868 Type* pNewType = pPointerType->pHead; 2869 TypeTag tag = pNewType->tag; 2870 switch (tag) { 2871 case TY_POINTER: 2872 case TY_INT: 2873 o2(0x008b); /* mov (%eax), %eax */ 2874 break; 2875 case TY_SHORT: 2876 o(0xbf0f); /* movswl (%eax), %eax */ 2877 ob(0); 2878 break; 2879 case TY_CHAR: 2880 o(0xbe0f); /* movsbl (%eax), %eax */ 2881 ob(0); /* add zero in code */ 2882 break; 2883 case TY_FLOAT: 2884 o2(0x00d9); // flds (%eax) 2885 break; 2886 case TY_DOUBLE: 2887 o2(0x00dd); // fldl (%eax) 2888 break; 2889 case TY_ARRAY: 2890 pNewType = pNewType->pTail; 2891 break; 2892 case TY_STRUCT: 2893 break; 2894 default: 2895 error("loadR0FromR0: unsupported type %d", tag); 2896 break; 2897 } 2898 setR0Type(pNewType); 2899 } 2900 2901 virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) { 2902 gmov(10, ea); /* leal EA, %eax */ 2903 setR0Type(pPointerType, et); 2904 } 2905 2906 virtual int leaForward(int ea, Type* pPointerType) { 2907 oad(0xb8, ea); /* mov $xx, %eax */ 2908 setR0Type(pPointerType); 2909 return getPC() - 4; 2910 } 2911 2912 virtual void convertR0Imp(Type* pType, bool isCast){ 2913 Type* pR0Type = getR0Type(); 2914 if (pR0Type == NULL) { 2915 assert(false); 2916 setR0Type(pType); 2917 return; 2918 } 2919 if (isPointerType(pType) && isPointerType(pR0Type)) { 2920 Type* pA = pR0Type; 2921 Type* pB = pType; 2922 // Array decays to pointer 2923 if (pA->tag == TY_ARRAY && pB->tag == TY_POINTER) { 2924 pA = pA->pTail; 2925 } 2926 if (! (typeEqual(pA, pB) 2927 || pB->pHead->tag == TY_VOID 2928 || (pA->tag == TY_POINTER && pB->tag == TY_POINTER && isCast) 2929 )) { 2930 error("Incompatible pointer or array types"); 2931 } 2932 } else if (bitsSame(pType, pR0Type)) { 2933 // do nothing special 2934 } else if (isFloatType(pType) && isFloatType(pR0Type)) { 2935 // do nothing special, both held in same register on x87. 2936 } else { 2937 TypeTag r0Tag = collapseType(pR0Type->tag); 2938 TypeTag destTag = collapseType(pType->tag); 2939 if (r0Tag == TY_INT && isFloatTag(destTag)) { 2940 // Convert R0 from int to float 2941 o(0x50); // push %eax 2942 o(0x2404DB); // fildl 0(%esp) 2943 o(0x58); // pop %eax 2944 } else if (isFloatTag(r0Tag) && destTag == TY_INT) { 2945 // Convert R0 from float to int. Complicated because 2946 // need to save and restore the rounding mode. 2947 o(0x50); // push %eax 2948 o(0x50); // push %eax 2949 o(0x02247cD9); // fnstcw 2(%esp) 2950 o(0x2444b70f); // movzwl 2(%esp), %eax 2951 o(0x02); 2952 o(0x0cb4); // movb $12, %ah 2953 o(0x24048966); // movw %ax, 0(%esp) 2954 o(0x242cd9); // fldcw 0(%esp) 2955 o(0x04245cdb); // fistpl 4(%esp) 2956 o(0x02246cd9); // fldcw 2(%esp) 2957 o(0x58); // pop %eax 2958 o(0x58); // pop %eax 2959 } else { 2960 error("Incompatible types old: %d new: %d", 2961 pR0Type->tag, pType->tag); 2962 } 2963 } 2964 setR0Type(pType); 2965 } 2966 2967 virtual int beginFunctionCallArguments() { 2968 return oad(0xec81, 0); /* sub $xxx, %esp */ 2969 } 2970 2971 virtual size_t storeR0ToArg(int l, Type* pArgType) { 2972 convertR0(pArgType); 2973 Type* pR0Type = getR0Type(); 2974 TypeTag r0ct = collapseType(pR0Type->tag); 2975 switch(r0ct) { 2976 case TY_INT: 2977 oad(0x248489, l); /* movl %eax, xxx(%esp) */ 2978 return 4; 2979 case TY_FLOAT: 2980 oad(0x249CD9, l); /* fstps xxx(%esp) */ 2981 return 4; 2982 case TY_DOUBLE: 2983 oad(0x249CDD, l); /* fstpl xxx(%esp) */ 2984 return 8; 2985 default: 2986 assert(false); 2987 return 0; 2988 } 2989 } 2990 2991 virtual void endFunctionCallArguments(Type* pDecl, int a, int l) { 2992 * (int*) a = l; 2993 } 2994 2995 virtual int callForward(int symbol, Type* pFunc) { 2996 assert(pFunc->tag == TY_FUNC); 2997 setR0Type(pFunc->pHead); 2998 return psym(0xe8, symbol); /* call xxx */ 2999 } 3000 3001 virtual void callIndirect(int l, Type* pFunc) { 3002 assert(pFunc->tag == TY_FUNC); 3003 popType(); // Get rid of indirect fn pointer type 3004 setR0Type(pFunc->pHead); 3005 oad(0x2494ff, l); /* call *xxx(%esp) */ 3006 } 3007 3008 virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) { 3009 assert(pDecl->tag == TY_FUNC); 3010 if (isIndirect) { 3011 l += 4; 3012 } 3013 if (l > 0) { 3014 oad(0xc481, l); /* add $xxx, %esp */ 3015 } 3016 } 3017 3018 virtual int jumpOffset() { 3019 return 5; 3020 } 3021 3022 /* output a symbol and patch all calls to it */ 3023 virtual void gsym(int t) { 3024 int n; 3025 int pc = getPC(); 3026 while (t) { 3027 n = *(int *) t; /* next value */ 3028 *(int *) t = pc - t - 4; 3029 t = n; 3030 } 3031 } 3032 3033 /* output a symbol and patch all calls to it, using absolute address */ 3034 virtual void resolveForward(int t) { 3035 int n; 3036 int pc = getPC(); 3037 while (t) { 3038 n = *(int *) t; /* next value */ 3039 *(int *) t = pc; 3040 t = n; 3041 } 3042 } 3043 3044 virtual int finishCompile() { 3045 size_t pagesize = 4096; 3046 size_t base = (size_t) getBase() & ~ (pagesize - 1); 3047 size_t top = ((size_t) getPC() + pagesize - 1) & ~ (pagesize - 1); 3048 int err = mprotect((void*) base, top - base, PROT_READ | PROT_WRITE | PROT_EXEC); 3049 if (err) { 3050 error("mprotect() failed: %d", errno); 3051 } 3052 return err; 3053 } 3054 3055 /** 3056 * Alignment (in bytes) for this type of data 3057 */ 3058 virtual size_t alignmentOf(Type* pType){ 3059 switch (pType->tag) { 3060 case TY_CHAR: 3061 return 1; 3062 case TY_SHORT: 3063 return 2; 3064 case TY_ARRAY: 3065 return alignmentOf(pType->pHead); 3066 case TY_STRUCT: 3067 return pType->pHead->alignment & 0x7fffffff; 3068 case TY_FUNC: 3069 error("alignment of func not supported"); 3070 return 1; 3071 default: 3072 return 4; 3073 } 3074 } 3075 3076 /** 3077 * Array element alignment (in bytes) for this type of data. 3078 */ 3079 virtual size_t sizeOf(Type* pType){ 3080 switch(pType->tag) { 3081 case TY_INT: 3082 return 4; 3083 case TY_SHORT: 3084 return 2; 3085 case TY_CHAR: 3086 return 1; 3087 case TY_FLOAT: 3088 return 4; 3089 case TY_DOUBLE: 3090 return 8; 3091 case TY_POINTER: 3092 return 4; 3093 case TY_ARRAY: 3094 return pType->length * sizeOf(pType->pHead); 3095 case TY_STRUCT: 3096 return pType->pHead->length; 3097 default: 3098 error("Unsupported type %d", pType->tag); 3099 return 0; 3100 } 3101 } 3102 3103 private: 3104 3105 /** Output 1 to 4 bytes. 3106 * 3107 */ 3108 void o(int n) { 3109 /* cannot use unsigned, so we must do a hack */ 3110 while (n && n != -1) { 3111 ob(n & 0xff); 3112 n = n >> 8; 3113 } 3114 } 3115 3116 /* Output exactly 2 bytes 3117 */ 3118 void o2(int n) { 3119 ob(n & 0xff); 3120 ob(0xff & (n >> 8)); 3121 } 3122 3123 /* psym is used to put an instruction with a data field which is a 3124 reference to a symbol. It is in fact the same as oad ! */ 3125 int psym(int n, int t) { 3126 return oad(n, t); 3127 } 3128 3129 /* instruction + address */ 3130 int oad(int n, int t) { 3131 o(n); 3132 int result = getPC(); 3133 o4(t); 3134 return result; 3135 } 3136 3137 static const int operatorHelper[]; 3138 3139 int decodeOp(int op) { 3140 if (op < 0 || op > OP_COUNT) { 3141 error("Out-of-range operator: %d\n", op); 3142 op = 0; 3143 } 3144 return operatorHelper[op]; 3145 } 3146 3147 void gmov(int l, int t) { 3148 o(l + 0x83); 3149 oad((t > -LOCAL && t < LOCAL) << 7 | 5, t); 3150 } 3151 3152 void setupFloatOperands() { 3153 Type* pR0Type = getR0Type(); 3154 Type* pTOSType = getTOSType(); 3155 TypeTag tagR0 = pR0Type->tag; 3156 TypeTag tagTOS = pTOSType->tag; 3157 bool isFloatR0 = isFloatTag(tagR0); 3158 bool isFloatTOS = isFloatTag(tagTOS); 3159 if (! isFloatR0) { 3160 // Convert R0 from int to float 3161 o(0x50); // push %eax 3162 o(0x2404DB); // fildl 0(%esp) 3163 o(0x58); // pop %eax 3164 } 3165 if (! isFloatTOS){ 3166 o(0x2404DB); // fildl 0(%esp); 3167 o(0x58); // pop %eax 3168 } else { 3169 if (tagTOS == TY_FLOAT) { 3170 o(0x2404d9); // flds (%esp) 3171 o(0x58); // pop %eax 3172 } else { 3173 o(0x2404dd); // fldl (%esp) 3174 o(0x58); // pop %eax 3175 o(0x58); // pop %eax 3176 } 3177 } 3178 popType(); 3179 } 3180 }; 3181 3182 #endif // PROVIDE_X86_CODEGEN 3183 3184 #ifdef PROVIDE_TRACE_CODEGEN 3185 class TraceCodeGenerator : public CodeGenerator { 3186 private: 3187 CodeGenerator* mpBase; 3188 3189 public: 3190 TraceCodeGenerator(CodeGenerator* pBase) { 3191 mpBase = pBase; 3192 } 3193 3194 virtual ~TraceCodeGenerator() { 3195 delete mpBase; 3196 } 3197 3198 virtual void init(ICodeBuf* pCodeBuf) { 3199 mpBase->init(pCodeBuf); 3200 } 3201 3202 void setErrorSink(ErrorSink* pErrorSink) { 3203 mpBase->setErrorSink(pErrorSink); 3204 } 3205 3206 /* returns address to patch with local variable size 3207 */ 3208 virtual int functionEntry(Type* pDecl) { 3209 int result = mpBase->functionEntry(pDecl); 3210 fprintf(stderr, "functionEntry(pDecl) -> %d\n", result); 3211 return result; 3212 } 3213 3214 virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) { 3215 fprintf(stderr, "functionExit(pDecl, %d, %d)\n", 3216 localVariableAddress, localVariableSize); 3217 mpBase->functionExit(pDecl, localVariableAddress, localVariableSize); 3218 } 3219 3220 /* load immediate value */ 3221 virtual void li(int t) { 3222 fprintf(stderr, "li(%d)\n", t); 3223 mpBase->li(t); 3224 } 3225 3226 virtual void loadFloat(int address, Type* pType) { 3227 fprintf(stderr, "loadFloat(%d, type=%d)\n", address, pType->tag); 3228 mpBase->loadFloat(address, pType); 3229 } 3230 3231 virtual void addStructOffsetR0(int offset, Type* pType) { 3232 fprintf(stderr, "addStructOffsetR0(%d, type=%d)\n", offset, pType->tag); 3233 mpBase->addStructOffsetR0(offset, pType); 3234 } 3235 3236 virtual int gjmp(int t) { 3237 int result = mpBase->gjmp(t); 3238 fprintf(stderr, "gjmp(%d) = %d\n", t, result); 3239 return result; 3240 } 3241 3242 /* l = 0: je, l == 1: jne */ 3243 virtual int gtst(bool l, int t) { 3244 int result = mpBase->gtst(l, t); 3245 fprintf(stderr, "gtst(%d,%d) = %d\n", l, t, result); 3246 return result; 3247 } 3248 3249 virtual void gcmp(int op) { 3250 fprintf(stderr, "gcmp(%d)\n", op); 3251 mpBase->gcmp(op); 3252 } 3253 3254 virtual void genOp(int op) { 3255 fprintf(stderr, "genOp(%d)\n", op); 3256 mpBase->genOp(op); 3257 } 3258 3259 3260 virtual void gUnaryCmp(int op) { 3261 fprintf(stderr, "gUnaryCmp(%d)\n", op); 3262 mpBase->gUnaryCmp(op); 3263 } 3264 3265 virtual void genUnaryOp(int op) { 3266 fprintf(stderr, "genUnaryOp(%d)\n", op); 3267 mpBase->genUnaryOp(op); 3268 } 3269 3270 virtual void pushR0() { 3271 fprintf(stderr, "pushR0()\n"); 3272 mpBase->pushR0(); 3273 } 3274 3275 virtual void over() { 3276 fprintf(stderr, "over()\n"); 3277 mpBase->over(); 3278 } 3279 3280 virtual void popR0() { 3281 fprintf(stderr, "popR0()\n"); 3282 mpBase->popR0(); 3283 } 3284 3285 virtual void storeR0ToTOS() { 3286 fprintf(stderr, "storeR0ToTOS()\n"); 3287 mpBase->storeR0ToTOS(); 3288 } 3289 3290 virtual void loadR0FromR0() { 3291 fprintf(stderr, "loadR0FromR0()\n"); 3292 mpBase->loadR0FromR0(); 3293 } 3294 3295 virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) { 3296 fprintf(stderr, "leaR0(%d, %d, %d)\n", ea, 3297 pPointerType->pHead->tag, et); 3298 mpBase->leaR0(ea, pPointerType, et); 3299 } 3300 3301 virtual int leaForward(int ea, Type* pPointerType) { 3302 fprintf(stderr, "leaForward(%d)\n", ea); 3303 return mpBase->leaForward(ea, pPointerType); 3304 } 3305 3306 virtual void convertR0Imp(Type* pType, bool isCast){ 3307 fprintf(stderr, "convertR0(pType tag=%d, %d)\n", pType->tag, isCast); 3308 mpBase->convertR0Imp(pType, isCast); 3309 } 3310 3311 virtual int beginFunctionCallArguments() { 3312 int result = mpBase->beginFunctionCallArguments(); 3313 fprintf(stderr, "beginFunctionCallArguments() = %d\n", result); 3314 return result; 3315 } 3316 3317 virtual size_t storeR0ToArg(int l, Type* pArgType) { 3318 fprintf(stderr, "storeR0ToArg(%d, pArgType=%d)\n", l, 3319 pArgType->tag); 3320 return mpBase->storeR0ToArg(l, pArgType); 3321 } 3322 3323 virtual void endFunctionCallArguments(Type* pDecl, int a, int l) { 3324 fprintf(stderr, "endFunctionCallArguments(%d, %d)\n", a, l); 3325 mpBase->endFunctionCallArguments(pDecl, a, l); 3326 } 3327 3328 virtual int callForward(int symbol, Type* pFunc) { 3329 int result = mpBase->callForward(symbol, pFunc); 3330 fprintf(stderr, "callForward(%d) = %d\n", symbol, result); 3331 return result; 3332 } 3333 3334 virtual void callIndirect(int l, Type* pFunc) { 3335 fprintf(stderr, "callIndirect(%d returntype = %d)\n", l, 3336 pFunc->pHead->tag); 3337 mpBase->callIndirect(l, pFunc); 3338 } 3339 3340 virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) { 3341 fprintf(stderr, "adjustStackAfterCall(pType, %d, %d)\n", l, isIndirect); 3342 mpBase->adjustStackAfterCall(pDecl, l, isIndirect); 3343 } 3344 3345 virtual int jumpOffset() { 3346 return mpBase->jumpOffset(); 3347 } 3348 3349 /* output a symbol and patch all calls to it */ 3350 virtual void gsym(int t) { 3351 fprintf(stderr, "gsym(%d)\n", t); 3352 mpBase->gsym(t); 3353 } 3354 3355 virtual void resolveForward(int t) { 3356 mpBase->resolveForward(t); 3357 } 3358 3359 virtual int finishCompile() { 3360 int result = mpBase->finishCompile(); 3361 fprintf(stderr, "finishCompile() = %d\n", result); 3362 return result; 3363 } 3364 3365 /** 3366 * Alignment (in bytes) for this type of data 3367 */ 3368 virtual size_t alignmentOf(Type* pType){ 3369 return mpBase->alignmentOf(pType); 3370 } 3371 3372 /** 3373 * Array element alignment (in bytes) for this type of data. 3374 */ 3375 virtual size_t sizeOf(Type* pType){ 3376 return mpBase->sizeOf(pType); 3377 } 3378 3379 virtual Type* getR0Type() { 3380 return mpBase->getR0Type(); 3381 } 3382 3383 virtual ExpressionType getR0ExpressionType() { 3384 return mpBase->getR0ExpressionType(); 3385 } 3386 3387 virtual void setR0ExpressionType(ExpressionType et) { 3388 mpBase->setR0ExpressionType(et); 3389 } 3390 3391 virtual size_t getExpressionStackDepth() { 3392 return mpBase->getExpressionStackDepth(); 3393 } 3394 3395 virtual void forceR0RVal() { 3396 return mpBase->forceR0RVal(); 3397 } 3398 }; 3399 3400 #endif // PROVIDE_TRACE_CODEGEN 3401 3402 class Arena { 3403 public: 3404 // Used to record a given allocation amount. 3405 // Used: 3406 // Mark mark = arena.mark(); 3407 // ... lots of arena.allocate() 3408 // arena.free(mark); 3409 3410 struct Mark { 3411 size_t chunk; 3412 size_t offset; 3413 }; 3414 3415 Arena() { 3416 mCurrentChunk = 0; 3417 Chunk start(CHUNK_SIZE); 3418 mData.push_back(start); 3419 } 3420 3421 ~Arena() { 3422 for(size_t i = 0; i < mData.size(); i++) { 3423 mData[i].free(); 3424 } 3425 } 3426 3427 // Alloc using the standard alignment size safe for any variable 3428 void* alloc(size_t size) { 3429 return alloc(size, 8); 3430 } 3431 3432 Mark mark(){ 3433 Mark result; 3434 result.chunk = mCurrentChunk; 3435 result.offset = mData[mCurrentChunk].mOffset; 3436 return result; 3437 } 3438 3439 void freeToMark(const Mark& mark) { 3440 mCurrentChunk = mark.chunk; 3441 mData[mCurrentChunk].mOffset = mark.offset; 3442 } 3443 3444 private: 3445 // Allocate memory aligned to a given size 3446 // and a given power-of-two-sized alignment (e.g. 1,2,4,8,...) 3447 // Memory is not zero filled. 3448 3449 void* alloc(size_t size, size_t alignment) { 3450 while (size > mData[mCurrentChunk].remainingCapacity(alignment)) { 3451 if (mCurrentChunk + 1 < mData.size()) { 3452 mCurrentChunk++; 3453 } else { 3454 size_t allocSize = CHUNK_SIZE; 3455 if (allocSize < size + alignment - 1) { 3456 allocSize = size + alignment - 1; 3457 } 3458 Chunk chunk(allocSize); 3459 mData.push_back(chunk); 3460 mCurrentChunk++; 3461 } 3462 } 3463 return mData[mCurrentChunk].allocate(size, alignment); 3464 } 3465 3466 static const size_t CHUNK_SIZE = 128*1024; 3467 // Note: this class does not deallocate its 3468 // memory when it's destroyed. It depends upon 3469 // its parent to deallocate the memory. 3470 struct Chunk { 3471 Chunk() { 3472 mpData = 0; 3473 mSize = 0; 3474 mOffset = 0; 3475 } 3476 3477 Chunk(size_t size) { 3478 mSize = size; 3479 mpData = (char*) malloc(size); 3480 mOffset = 0; 3481 } 3482 3483 ~Chunk() { 3484 // Doesn't deallocate memory. 3485 } 3486 3487 void* allocate(size_t size, size_t alignment) { 3488 size_t alignedOffset = aligned(mOffset, alignment); 3489 void* result = mpData + alignedOffset; 3490 mOffset = alignedOffset + size; 3491 return result; 3492 } 3493 3494 void free() { 3495 if (mpData) { 3496 ::free(mpData); 3497 mpData = 0; 3498 } 3499 } 3500 3501 size_t remainingCapacity(size_t alignment) { 3502 return aligned(mSize, alignment) - aligned(mOffset, alignment); 3503 } 3504 3505 // Assume alignment is a power of two 3506 inline size_t aligned(size_t v, size_t alignment) { 3507 size_t mask = alignment-1; 3508 return (v + mask) & ~mask; 3509 } 3510 3511 char* mpData; 3512 size_t mSize; 3513 size_t mOffset; 3514 }; 3515 3516 size_t mCurrentChunk; 3517 3518 Vector<Chunk> mData; 3519 }; 3520 3521 struct VariableInfo; 3522 3523 struct Token { 3524 int hash; 3525 size_t length; 3526 char* pText; 3527 tokenid_t id; 3528 3529 // Current values for the token 3530 char* mpMacroDefinition; 3531 VariableInfo* mpVariableInfo; 3532 VariableInfo* mpStructInfo; 3533 }; 3534 3535 class TokenTable { 3536 public: 3537 // Don't use 0..0xff, allows characters and operators to be tokens too. 3538 3539 static const int TOKEN_BASE = 0x100; 3540 TokenTable() { 3541 mpMap = hashmapCreate(128, hashFn, equalsFn); 3542 } 3543 3544 ~TokenTable() { 3545 hashmapFree(mpMap); 3546 } 3547 3548 void setArena(Arena* pArena) { 3549 mpArena = pArena; 3550 } 3551 3552 // Returns a token for a given string of characters. 3553 tokenid_t intern(const char* pText, size_t length) { 3554 Token probe; 3555 int hash = hashmapHash((void*) pText, length); 3556 { 3557 Token probe; 3558 probe.hash = hash; 3559 probe.length = length; 3560 probe.pText = (char*) pText; 3561 Token* pValue = (Token*) hashmapGet(mpMap, &probe); 3562 if (pValue) { 3563 return pValue->id; 3564 } 3565 } 3566 3567 Token* pToken = (Token*) mpArena->alloc(sizeof(Token)); 3568 memset(pToken, 0, sizeof(*pToken)); 3569 pToken->hash = hash; 3570 pToken->length = length; 3571 pToken->pText = (char*) mpArena->alloc(length + 1); 3572 memcpy(pToken->pText, pText, length); 3573 pToken->pText[length] = 0; 3574 pToken->id = mTokens.size() + TOKEN_BASE; 3575 mTokens.push_back(pToken); 3576 hashmapPut(mpMap, pToken, pToken); 3577 return pToken->id; 3578 } 3579 3580 // Return the Token for a given tokenid. 3581 Token& operator[](tokenid_t id) { 3582 return *mTokens[id - TOKEN_BASE]; 3583 } 3584 3585 inline size_t size() { 3586 return mTokens.size(); 3587 } 3588 3589 private: 3590 3591 static int hashFn(void* pKey) { 3592 Token* pToken = (Token*) pKey; 3593 return pToken->hash; 3594 } 3595 3596 static bool equalsFn(void* keyA, void* keyB) { 3597 Token* pTokenA = (Token*) keyA; 3598 Token* pTokenB = (Token*) keyB; 3599 // Don't need to compare hash values, they should always be equal 3600 return pTokenA->length == pTokenB->length 3601 && strcmp(pTokenA->pText, pTokenB->pText) == 0; 3602 } 3603 3604 Hashmap* mpMap; 3605 Vector<Token*> mTokens; 3606 Arena* mpArena; 3607 }; 3608 3609 class InputStream { 3610 public: 3611 virtual ~InputStream() {} 3612 virtual int getChar() = 0; 3613 }; 3614 3615 class TextInputStream : public InputStream { 3616 public: 3617 TextInputStream(const char* text, size_t textLength) 3618 : pText(text), mTextLength(textLength), mPosition(0) { 3619 } 3620 3621 virtual int getChar() { 3622 return mPosition < mTextLength ? pText[mPosition++] : EOF; 3623 } 3624 3625 private: 3626 const char* pText; 3627 size_t mTextLength; 3628 size_t mPosition; 3629 }; 3630 3631 class String { 3632 public: 3633 String() { 3634 mpBase = 0; 3635 mUsed = 0; 3636 mSize = 0; 3637 } 3638 3639 String(const char* item, int len, bool adopt) { 3640 if (len < 0) { 3641 len = strlen(item); 3642 } 3643 if (adopt) { 3644 mpBase = (char*) item; 3645 mUsed = len; 3646 mSize = len + 1; 3647 } else { 3648 mpBase = 0; 3649 mUsed = 0; 3650 mSize = 0; 3651 appendBytes(item, len); 3652 } 3653 } 3654 3655 String(const String& other) { 3656 mpBase = 0; 3657 mUsed = 0; 3658 mSize = 0; 3659 appendBytes(other.getUnwrapped(), other.len()); 3660 } 3661 3662 ~String() { 3663 if (mpBase) { 3664 free(mpBase); 3665 } 3666 } 3667 3668 String& operator=(const String& other) { 3669 clear(); 3670 appendBytes(other.getUnwrapped(), other.len()); 3671 return *this; 3672 } 3673 3674 inline char* getUnwrapped() const { 3675 return mpBase; 3676 } 3677 3678 void clear() { 3679 mUsed = 0; 3680 if (mSize > 0) { 3681 mpBase[0] = 0; 3682 } 3683 } 3684 3685 void appendCStr(const char* s) { 3686 appendBytes(s, strlen(s)); 3687 } 3688 3689 void appendBytes(const char* s, int n) { 3690 memcpy(ensure(n), s, n + 1); 3691 } 3692 3693 void append(char c) { 3694 * ensure(1) = c; 3695 } 3696 3697 void append(String& other) { 3698 appendBytes(other.getUnwrapped(), other.len()); 3699 } 3700 3701 char* orphan() { 3702 char* result = mpBase; 3703 mpBase = 0; 3704 mUsed = 0; 3705 mSize = 0; 3706 return result; 3707 } 3708 3709 void printf(const char* fmt,...) { 3710 va_list ap; 3711 va_start(ap, fmt); 3712 vprintf(fmt, ap); 3713 va_end(ap); 3714 } 3715 3716 void vprintf(const char* fmt, va_list ap) { 3717 char* temp; 3718 int numChars = vasprintf(&temp, fmt, ap); 3719 memcpy(ensure(numChars), temp, numChars+1); 3720 free(temp); 3721 } 3722 3723 inline size_t len() const { 3724 return mUsed; 3725 } 3726 3727 private: 3728 char* ensure(int n) { 3729 size_t newUsed = mUsed + n; 3730 if (newUsed > mSize) { 3731 size_t newSize = mSize * 2 + 10; 3732 if (newSize < newUsed) { 3733 newSize = newUsed; 3734 } 3735 mpBase = (char*) realloc(mpBase, newSize + 1); 3736 mSize = newSize; 3737 } 3738 mpBase[newUsed] = '\0'; 3739 char* result = mpBase + mUsed; 3740 mUsed = newUsed; 3741 return result; 3742 } 3743 3744 char* mpBase; 3745 size_t mUsed; 3746 size_t mSize; 3747 }; 3748 3749 void internKeywords() { 3750 // Note: order has to match TOK_ constants 3751 static const char* keywords[] = { 3752 "int", 3753 "char", 3754 "void", 3755 "if", 3756 "else", 3757 "while", 3758 "break", 3759 "return", 3760 "for", 3761 "auto", 3762 "case", 3763 "const", 3764 "continue", 3765 "default", 3766 "do", 3767 "double", 3768 "enum", 3769 "extern", 3770 "float", 3771 "goto", 3772 "long", 3773 "register", 3774 "short", 3775 "signed", 3776 "sizeof", 3777 "static", 3778 "struct", 3779 "switch", 3780 "typedef", 3781 "union", 3782 "unsigned", 3783 "volatile", 3784 "_Bool", 3785 "_Complex", 3786 "_Imaginary", 3787 "inline", 3788 "restrict", 3789 3790 // predefined tokens that can also be symbols start here: 3791 "pragma", 3792 "define", 3793 "line", 3794 0}; 3795 3796 for(int i = 0; keywords[i]; i++) { 3797 mTokenTable.intern(keywords[i], strlen(keywords[i])); 3798 } 3799 } 3800 3801 struct InputState { 3802 InputStream* pStream; 3803 int oldCh; 3804 }; 3805 3806 struct VariableInfo { 3807 void* pAddress; 3808 void* pForward; // For a forward direction, linked list of data to fix up 3809 tokenid_t tok; 3810 size_t level; 3811 VariableInfo* pOldDefinition; 3812 Type* pType; 3813 bool isStructTag; 3814 }; 3815 3816 class SymbolStack { 3817 public: 3818 SymbolStack() { 3819 mpArena = 0; 3820 mpTokenTable = 0; 3821 } 3822 3823 void setArena(Arena* pArena) { 3824 mpArena = pArena; 3825 } 3826 3827 void setTokenTable(TokenTable* pTokenTable) { 3828 mpTokenTable = pTokenTable; 3829 } 3830 3831 void pushLevel() { 3832 Mark mark; 3833 mark.mArenaMark = mpArena->mark(); 3834 mark.mSymbolHead = mStack.size(); 3835 mLevelStack.push_back(mark); 3836 } 3837 3838 void popLevel() { 3839 // Undo any shadowing that was done: 3840 Mark mark = mLevelStack.back(); 3841 mLevelStack.pop_back(); 3842 while (mStack.size() > mark.mSymbolHead) { 3843 VariableInfo* pV = mStack.back(); 3844 mStack.pop_back(); 3845 if (pV->isStructTag) { 3846 (*mpTokenTable)[pV->tok].mpStructInfo = pV->pOldDefinition; 3847 } else { 3848 (*mpTokenTable)[pV->tok].mpVariableInfo = pV->pOldDefinition; 3849 } 3850 } 3851 mpArena->freeToMark(mark.mArenaMark); 3852 } 3853 3854 bool isDefinedAtCurrentLevel(tokenid_t tok) { 3855 VariableInfo* pV = (*mpTokenTable)[tok].mpVariableInfo; 3856 return pV && pV->level == level(); 3857 } 3858 3859 bool isStructTagDefinedAtCurrentLevel(tokenid_t tok) { 3860 VariableInfo* pV = (*mpTokenTable)[tok].mpStructInfo; 3861 return pV && pV->level == level(); 3862 } 3863 3864 VariableInfo* add(tokenid_t tok) { 3865 Token& token = (*mpTokenTable)[tok]; 3866 VariableInfo* pOldV = token.mpVariableInfo; 3867 VariableInfo* pNewV = 3868 (VariableInfo*) mpArena->alloc(sizeof(VariableInfo)); 3869 memset(pNewV, 0, sizeof(VariableInfo)); 3870 pNewV->tok = tok; 3871 pNewV->level = level(); 3872 pNewV->pOldDefinition = pOldV; 3873 token.mpVariableInfo = pNewV; 3874 mStack.push_back(pNewV); 3875 return pNewV; 3876 } 3877 3878 VariableInfo* addStructTag(tokenid_t tok) { 3879 Token& token = (*mpTokenTable)[tok]; 3880 VariableInfo* pOldS = token.mpStructInfo; 3881 VariableInfo* pNewS = 3882 (VariableInfo*) mpArena->alloc(sizeof(VariableInfo)); 3883 memset(pNewS, 0, sizeof(VariableInfo)); 3884 pNewS->tok = tok; 3885 pNewS->level = level(); 3886 pNewS->isStructTag = true; 3887 pNewS->pOldDefinition = pOldS; 3888 token.mpStructInfo = pNewS; 3889 mStack.push_back(pNewS); 3890 return pNewS; 3891 } 3892 3893 VariableInfo* add(Type* pType) { 3894 VariableInfo* pVI = add(pType->id); 3895 pVI->pType = pType; 3896 return pVI; 3897 } 3898 3899 void forEach(bool (*fn)(VariableInfo*, void*), void* context) { 3900 for (size_t i = 0; i < mStack.size(); i++) { 3901 if (! fn(mStack[i], context)) { 3902 break; 3903 } 3904 } 3905 } 3906 3907 private: 3908 inline size_t level() { 3909 return mLevelStack.size(); 3910 } 3911 3912 struct Mark { 3913 Arena::Mark mArenaMark; 3914 size_t mSymbolHead; 3915 }; 3916 3917 Arena* mpArena; 3918 TokenTable* mpTokenTable; 3919 Vector<VariableInfo*> mStack; 3920 Vector<Mark> mLevelStack; 3921 }; 3922 3923 struct MacroState { 3924 tokenid_t name; // Name of the current macro we are expanding 3925 char* dptr; // point to macro text during macro playback 3926 int dch; // Saves old value of ch during a macro playback 3927 }; 3928 3929 #define MACRO_NESTING_MAX 32 3930 MacroState macroState[MACRO_NESTING_MAX]; 3931 int macroLevel; // -1 means not playing any macro. 3932 3933 int ch; // Current input character, or EOF 3934 tokenid_t tok; // token 3935 intptr_t tokc; // token extra info 3936 double tokd; // floating point constant value 3937 int tokl; // token operator level 3938 intptr_t rsym; // return symbol 3939 Type* pReturnType; // type of the current function's return. 3940 intptr_t loc; // local variable index 3941 char* glo; // global variable index 3942 String mTokenString; 3943 bool mbSuppressMacroExpansion; 3944 char* pGlobalBase; 3945 ACCSymbolLookupFn mpSymbolLookupFn; 3946 void* mpSymbolLookupContext; 3947 3948 // Arena for the duration of the compile 3949 Arena mGlobalArena; 3950 // Arena for data that's only needed when compiling a single function 3951 Arena mLocalArena; 3952 3953 Arena* mpCurrentArena; 3954 3955 TokenTable mTokenTable; 3956 SymbolStack mGlobals; 3957 SymbolStack mLocals; 3958 3959 SymbolStack* mpCurrentSymbolStack; 3960 3961 // Prebuilt types, makes things slightly faster. 3962 Type* mkpInt; // int 3963 Type* mkpShort; // short 3964 Type* mkpChar; // char 3965 Type* mkpVoid; // void 3966 Type* mkpFloat; 3967 Type* mkpDouble; 3968 Type* mkpIntFn; 3969 Type* mkpIntPtr; 3970 Type* mkpCharPtr; 3971 Type* mkpFloatPtr; 3972 Type* mkpDoublePtr; 3973 Type* mkpPtrIntFn; 3974 3975 InputStream* file; 3976 int mLineNumber; 3977 bool mbBumpLine; 3978 3979 ICodeBuf* pCodeBuf; 3980 CodeGenerator* pGen; 3981 3982 String mErrorBuf; 3983 3984 String mPragmas; 3985 int mPragmaStringCount; 3986 int mCompileResult; 3987 3988 static const int ALLOC_SIZE = 99999; 3989 3990 static const int TOK_DUMMY = 1; 3991 static const int TOK_NUM = 2; 3992 static const int TOK_NUM_FLOAT = 3; 3993 static const int TOK_NUM_DOUBLE = 4; 3994 static const int TOK_OP_ASSIGNMENT = 5; 3995 static const int TOK_OP_ARROW = 6; 3996 3997 // 3..255 are character and/or operators 3998 3999 // Keywords start at 0x100 and increase by 1 4000 // Order has to match string list in "internKeywords". 4001 enum { 4002 TOK_KEYWORD = TokenTable::TOKEN_BASE, 4003 TOK_INT = TOK_KEYWORD, 4004 TOK_CHAR, 4005 TOK_VOID, 4006 TOK_IF, 4007 TOK_ELSE, 4008 TOK_WHILE, 4009 TOK_BREAK, 4010 TOK_RETURN, 4011 TOK_FOR, 4012 TOK_AUTO, 4013 TOK_CASE, 4014 TOK_CONST, 4015 TOK_CONTINUE, 4016 TOK_DEFAULT, 4017 TOK_DO, 4018 TOK_DOUBLE, 4019 TOK_ENUM, 4020 TOK_EXTERN, 4021 TOK_FLOAT, 4022 TOK_GOTO, 4023 TOK_LONG, 4024 TOK_REGISTER, 4025 TOK_SHORT, 4026 TOK_SIGNED, 4027 TOK_SIZEOF, 4028 TOK_STATIC, 4029 TOK_STRUCT, 4030 TOK_SWITCH, 4031 TOK_TYPEDEF, 4032 TOK_UNION, 4033 TOK_UNSIGNED, 4034 TOK_VOLATILE, 4035 TOK__BOOL, 4036 TOK__COMPLEX, 4037 TOK__IMAGINARY, 4038 TOK_INLINE, 4039 TOK_RESTRICT, 4040 4041 // Symbols start after keywords 4042 4043 TOK_SYMBOL, 4044 TOK_PRAGMA = TOK_SYMBOL, 4045 TOK_DEFINE, 4046 TOK_LINE 4047 }; 4048 4049 static const int LOCAL = 0x200; 4050 4051 /* tokens in string heap */ 4052 static const int TAG_TOK = ' '; 4053 4054 static const int OP_INCREMENT = 0; 4055 static const int OP_DECREMENT = 1; 4056 static const int OP_MUL = 2; 4057 static const int OP_DIV = 3; 4058 static const int OP_MOD = 4; 4059 static const int OP_PLUS = 5; 4060 static const int OP_MINUS = 6; 4061 static const int OP_SHIFT_LEFT = 7; 4062 static const int OP_SHIFT_RIGHT = 8; 4063 static const int OP_LESS_EQUAL = 9; 4064 static const int OP_GREATER_EQUAL = 10; 4065 static const int OP_LESS = 11; 4066 static const int OP_GREATER = 12; 4067 static const int OP_EQUALS = 13; 4068 static const int OP_NOT_EQUALS = 14; 4069 static const int OP_LOGICAL_AND = 15; 4070 static const int OP_LOGICAL_OR = 16; 4071 static const int OP_BIT_AND = 17; 4072 static const int OP_BIT_XOR = 18; 4073 static const int OP_BIT_OR = 19; 4074 static const int OP_BIT_NOT = 20; 4075 static const int OP_LOGICAL_NOT = 21; 4076 static const int OP_COUNT = 22; 4077 4078 /* Operators are searched from front, the two-character operators appear 4079 * before the single-character operators with the same first character. 4080 * @ is used to pad out single-character operators. 4081 */ 4082 static const char* operatorChars; 4083 static const char operatorLevel[]; 4084 4085 /* Called when we detect an internal problem. Does nothing in production. 4086 * 4087 */ 4088 void internalError() { 4089 * (char*) 0 = 0; 4090 } 4091 4092 void assertImpl(bool isTrue, int line) { 4093 if (!isTrue) { 4094 LOGD("%d: assertion failed at line %s:%d.", mLineNumber, __FILE__, line); 4095 internalError(); 4096 } 4097 } 4098 4099 bool isSymbol(tokenid_t t) { 4100 return t >= TOK_SYMBOL && 4101 ((size_t) (t-TOK_SYMBOL)) < mTokenTable.size(); 4102 } 4103 4104 bool isSymbolOrKeyword(tokenid_t t) { 4105 return t >= TOK_KEYWORD && 4106 ((size_t) (t-TOK_KEYWORD)) < mTokenTable.size(); 4107 } 4108 4109 VariableInfo* VI(tokenid_t t) { 4110 assert(isSymbol(t)); 4111 VariableInfo* pV = mTokenTable[t].mpVariableInfo; 4112 if (pV && pV->tok != t) { 4113 internalError(); 4114 } 4115 return pV; 4116 } 4117 4118 inline bool isDefined(tokenid_t t) { 4119 return t >= TOK_SYMBOL && VI(t) != 0; 4120 } 4121 4122 const char* nameof(tokenid_t t) { 4123 assert(isSymbolOrKeyword(t)); 4124 return mTokenTable[t].pText; 4125 } 4126 4127 void pdef(int t) { 4128 mTokenString.append(t); 4129 } 4130 4131 void inp() { 4132 // Close any totally empty macros. We leave them on the stack until now 4133 // so that we know which macros are being expanded when checking if the 4134 // last token in the macro is a macro that's already being expanded. 4135 while (macroLevel >= 0 && macroState[macroLevel].dptr == NULL) { 4136 macroLevel--; 4137 } 4138 if (macroLevel >= 0) { 4139 ch = *macroState[macroLevel].dptr++; 4140 if (ch == 0) { 4141 ch = macroState[macroLevel].dch; 4142 macroState[macroLevel].dptr = NULL; // This macro's done 4143 } 4144 } else { 4145 if (mbBumpLine) { 4146 mLineNumber++; 4147 mbBumpLine = false; 4148 } 4149 ch = file->getChar(); 4150 if (ch == '\n') { 4151 mbBumpLine = true; 4152 } 4153 } 4154 #if 0 4155 printf("ch='%c' 0x%x\n", ch, ch); 4156 #endif 4157 } 4158 4159 int isid() { 4160 return isalnum(ch) | (ch == '_'); 4161 } 4162 4163 int decodeHex(int c) { 4164 if (isdigit(c)) { 4165 c -= '0'; 4166 } else if (c <= 'F') { 4167 c = c - 'A' + 10; 4168 } else { 4169 c =c - 'a' + 10; 4170 } 4171 return c; 4172 } 4173 4174 /* read a character constant, advances ch to after end of constant */ 4175 int getq() { 4176 int val = ch; 4177 if (ch == '\\') { 4178 inp(); 4179 if (isoctal(ch)) { 4180 // 1 to 3 octal characters. 4181 val = 0; 4182 for(int i = 0; i < 3; i++) { 4183 if (isoctal(ch)) { 4184 val = (val << 3) + ch - '0'; 4185 inp(); 4186 } 4187 } 4188 return val; 4189 } else if (ch == 'x' || ch == 'X') { 4190 // N hex chars 4191 inp(); 4192 if (! isxdigit(ch)) { 4193 error("'x' character escape requires at least one digit."); 4194 } else { 4195 val = 0; 4196 while (isxdigit(ch)) { 4197 val = (val << 4) + decodeHex(ch); 4198 inp(); 4199 } 4200 } 4201 } else { 4202 int val = ch; 4203 switch (ch) { 4204 case 'a': 4205 val = '\a'; 4206 break; 4207 case 'b': 4208 val = '\b'; 4209 break; 4210 case 'f': 4211 val = '\f'; 4212 break; 4213 case 'n': 4214 val = '\n'; 4215 break; 4216 case 'r': 4217 val = '\r'; 4218 break; 4219 case 't': 4220 val = '\t'; 4221 break; 4222 case 'v': 4223 val = '\v'; 4224 break; 4225 case '\\': 4226 val = '\\'; 4227 break; 4228 case '\'': 4229 val = '\''; 4230 break; 4231 case '"': 4232 val = '"'; 4233 break; 4234 case '?': 4235 val = '?'; 4236 break; 4237 default: 4238 error("Undefined character escape %c", ch); 4239 break; 4240 } 4241 inp(); 4242 return val; 4243 } 4244 } else { 4245 inp(); 4246 } 4247 return val; 4248 } 4249 4250 static bool isoctal(int ch) { 4251 return ch >= '0' && ch <= '7'; 4252 } 4253 4254 bool acceptCh(int c) { 4255 bool result = c == ch; 4256 if (result) { 4257 pdef(ch); 4258 inp(); 4259 } 4260 return result; 4261 } 4262 4263 bool acceptDigitsCh() { 4264 bool result = false; 4265 while (isdigit(ch)) { 4266 result = true; 4267 pdef(ch); 4268 inp(); 4269 } 4270 return result; 4271 } 4272 4273 void parseFloat() { 4274 tok = TOK_NUM_DOUBLE; 4275 // mTokenString already has the integral part of the number. 4276 if(mTokenString.len() == 0) { 4277 mTokenString.append('0'); 4278 } 4279 acceptCh('.'); 4280 acceptDigitsCh(); 4281 if (acceptCh('e') || acceptCh('E')) { 4282 acceptCh('-') || acceptCh('+'); 4283 acceptDigitsCh(); 4284 } 4285 if (ch == 'f' || ch == 'F') { 4286 tok = TOK_NUM_FLOAT; 4287 inp(); 4288 } else if (ch == 'l' || ch == 'L') { 4289 inp(); 4290 error("Long floating point constants not supported."); 4291 } 4292 char* pText = mTokenString.getUnwrapped(); 4293 char* pEnd = pText + strlen(pText); 4294 char* pEndPtr = 0; 4295 errno = 0; 4296 if (tok == TOK_NUM_FLOAT) { 4297 tokd = strtof(pText, &pEndPtr); 4298 } else { 4299 tokd = strtod(pText, &pEndPtr); 4300 } 4301 if (errno || pEndPtr != pEnd) { 4302 error("Can't parse constant: %s", pText); 4303 } 4304 // fprintf(stderr, "float constant: %s (%d) %g\n", pText, tok, tokd); 4305 } 4306 4307 bool currentlyBeingExpanded(tokenid_t id) { 4308 for (int i = 0; i <= macroLevel; i++) { 4309 if (macroState[macroLevel].name == id) { 4310 return true; 4311 } 4312 } 4313 return false; 4314 } 4315 4316 void next() { 4317 int l, a; 4318 4319 while (isspace(ch) | (ch == '#')) { 4320 if (ch == '#') { 4321 inp(); 4322 next(); 4323 if (tok == TOK_DEFINE) { 4324 doDefine(); 4325 } else if (tok == TOK_PRAGMA) { 4326 doPragma(); 4327 } else if (tok == TOK_LINE) { 4328 doLine(); 4329 } else { 4330 error("Unsupported preprocessor directive \"%s\"", 4331 mTokenString.getUnwrapped()); 4332 } 4333 } 4334 inp(); 4335 } 4336 tokl = 0; 4337 tok = ch; 4338 /* encode identifiers & numbers */ 4339 if (isdigit(ch) || ch == '.') { 4340 // Start of a numeric constant. Could be integer, float, or 4341 // double, won't know until we look further. 4342 mTokenString.clear(); 4343 pdef(ch); 4344 inp(); 4345 if (tok == '.' && !isdigit(ch)) { 4346 goto done; 4347 } 4348 int base = 10; 4349 if (tok == '0') { 4350 if (ch == 'x' || ch == 'X') { 4351 base = 16; 4352 tok = TOK_NUM; 4353 tokc = 0; 4354 inp(); 4355 while ( isxdigit(ch) ) { 4356 tokc = (tokc << 4) + decodeHex(ch); 4357 inp(); 4358 } 4359 } else if (isoctal(ch)){ 4360 base = 8; 4361 tok = TOK_NUM; 4362 tokc = 0; 4363 while ( isoctal(ch) ) { 4364 tokc = (tokc << 3) + (ch - '0'); 4365 inp(); 4366 } 4367 } 4368 } else if (isdigit(tok)){ 4369 acceptDigitsCh(); 4370 } 4371 if (base == 10) { 4372 if (tok == '.' || ch == '.' || ch == 'e' || ch == 'E') { 4373 parseFloat(); 4374 } else { 4375 // It's an integer constant 4376 char* pText = mTokenString.getUnwrapped(); 4377 char* pEnd = pText + strlen(pText); 4378 char* pEndPtr = 0; 4379 errno = 0; 4380 tokc = strtol(pText, &pEndPtr, base); 4381 if (errno || pEndPtr != pEnd) { 4382 error("Can't parse constant: %s %d %d", pText, base, errno); 4383 } 4384 tok = TOK_NUM; 4385 } 4386 } 4387 } else if (isid()) { 4388 mTokenString.clear(); 4389 while (isid()) { 4390 pdef(ch); 4391 inp(); 4392 } 4393 tok = mTokenTable.intern(mTokenString.getUnwrapped(), mTokenString.len()); 4394 if (! mbSuppressMacroExpansion) { 4395 // Is this a macro? 4396 char* pMacroDefinition = mTokenTable[tok].mpMacroDefinition; 4397 if (pMacroDefinition && !currentlyBeingExpanded(tok)) { 4398 // Yes, it is a macro 4399 #if 0 4400 printf("Expanding macro %s -> %s", 4401 mTokenString.getUnwrapped(), pMacroDefinition); 4402 #endif 4403 if (macroLevel >= MACRO_NESTING_MAX-1) { 4404 error("Too many levels of macro recursion."); 4405 } else { 4406 macroLevel++; 4407 macroState[macroLevel].name = tok; 4408 macroState[macroLevel].dptr = pMacroDefinition; 4409 macroState[macroLevel].dch = ch; 4410 inp(); 4411 next(); 4412 } 4413 } 4414 } 4415 } else { 4416 inp(); 4417 if (tok == '\'') { 4418 tok = TOK_NUM; 4419 tokc = getq(); 4420 if (ch != '\'') { 4421 error("Expected a ' character, got %c", ch); 4422 } else { 4423 inp(); 4424 } 4425 } else if ((tok == '/') & (ch == '*')) { 4426 inp(); 4427 while (ch && ch != EOF) { 4428 while (ch != '*' && ch != EOF) 4429 inp(); 4430 inp(); 4431 if (ch == '/') 4432 ch = 0; 4433 } 4434 if (ch == EOF) { 4435 error("End of file inside comment."); 4436 } 4437 inp(); 4438 next(); 4439 } else if ((tok == '/') & (ch == '/')) { 4440 inp(); 4441 while (ch && (ch != '\n') && (ch != EOF)) { 4442 inp(); 4443 } 4444 inp(); 4445 next(); 4446 } else if ((tok == '-') & (ch == '>')) { 4447 inp(); 4448 tok = TOK_OP_ARROW; 4449 } else { 4450 const char* t = operatorChars; 4451 int opIndex = 0; 4452 while ((l = *t++) != 0) { 4453 a = *t++; 4454 tokl = operatorLevel[opIndex]; 4455 tokc = opIndex; 4456 if ((l == tok) & ((a == ch) | (a == '@'))) { 4457 #if 0 4458 printf("%c%c -> tokl=%d tokc=0x%x\n", 4459 l, a, tokl, tokc); 4460 #endif 4461 if (a == ch) { 4462 inp(); 4463 tok = TOK_DUMMY; /* dummy token for double tokens */ 4464 } 4465 /* check for op=, valid for * / % + - << >> & ^ | */ 4466 if (ch == '=' && 4467 ((tokl >= 1 && tokl <= 3) 4468 || (tokl >=6 && tokl <= 8)) ) { 4469 inp(); 4470 tok = TOK_OP_ASSIGNMENT; 4471 } 4472 break; 4473 } 4474 opIndex++; 4475 } 4476 if (l == 0) { 4477 tokl = 0; 4478 tokc = 0; 4479 } 4480 } 4481 } 4482 4483 done: ; 4484 #if 0 4485 { 4486 String buf; 4487 decodeToken(buf, tok, true); 4488 fprintf(stderr, "%s\n", buf.getUnwrapped()); 4489 } 4490 #endif 4491 } 4492 4493 void doDefine() { 4494 mbSuppressMacroExpansion = true; 4495 next(); 4496 mbSuppressMacroExpansion = false; 4497 tokenid_t name = tok; 4498 if (ch == '(') { 4499 error("Defines with arguments not supported"); 4500 return; 4501 } 4502 while (isspace(ch)) { 4503 inp(); 4504 } 4505 String value; 4506 bool appendToValue = true; 4507 while (ch != '\n' && ch != EOF) { 4508 // Check for '//' comments. 4509 if (appendToValue && ch == '/') { 4510 inp(); 4511 if (ch == '/') { 4512 appendToValue = false; 4513 } else { 4514 value.append('/'); 4515 } 4516 } 4517 if (appendToValue && ch != EOF) { 4518 value.append(ch); 4519 } 4520 inp(); 4521 } 4522 char* pDefn = (char*)mGlobalArena.alloc(value.len() + 1); 4523 memcpy(pDefn, value.getUnwrapped(), value.len()); 4524 pDefn[value.len()] = 0; 4525 mTokenTable[name].mpMacroDefinition = pDefn; 4526 #if 0 4527 { 4528 String buf; 4529 decodeToken(buf, name, true); 4530 fprintf(stderr, "define %s = \"%s\"\n", buf.getUnwrapped(), pDefn); 4531 } 4532 #endif 4533 } 4534 4535 void doPragma() { 4536 // # pragma name(val) 4537 int state = 0; 4538 while(ch != EOF && ch != '\n' && state < 10) { 4539 switch(state) { 4540 case 0: 4541 if (isspace(ch)) { 4542 inp(); 4543 } else { 4544 state++; 4545 } 4546 break; 4547 case 1: 4548 if (isalnum(ch)) { 4549 mPragmas.append(ch); 4550 inp(); 4551 } else if (ch == '(') { 4552 mPragmas.append(0); 4553 inp(); 4554 state++; 4555 } else { 4556 state = 11; 4557 } 4558 break; 4559 case 2: 4560 if (isalnum(ch)) { 4561 mPragmas.append(ch); 4562 inp(); 4563 } else if (ch == ')') { 4564 mPragmas.append(0); 4565 inp(); 4566 state = 10; 4567 } else { 4568 state = 11; 4569 } 4570 break; 4571 } 4572 } 4573 if(state != 10) { 4574 error("Unexpected pragma syntax"); 4575 } 4576 mPragmaStringCount += 2; 4577 } 4578 4579 void doLine() { 4580 // # line number { "filename "} 4581 next(); 4582 if (tok != TOK_NUM) { 4583 error("Expected a line-number"); 4584 } else { 4585 mLineNumber = tokc-1; // The end-of-line will increment it. 4586 } 4587 while(ch != EOF && ch != '\n') { 4588 inp(); 4589 } 4590 } 4591 4592 virtual void verror(const char* fmt, va_list ap) { 4593 mErrorBuf.printf("%ld: ", mLineNumber); 4594 mErrorBuf.vprintf(fmt, ap); 4595 mErrorBuf.printf("\n"); 4596 } 4597 4598 void skip(intptr_t c) { 4599 if (!accept(c)) { 4600 error("'%c' expected", c); 4601 } 4602 } 4603 4604 bool accept(intptr_t c) { 4605 if (tok == c) { 4606 next(); 4607 return true; 4608 } 4609 return false; 4610 } 4611 4612 bool acceptStringLiteral() { 4613 if (tok == '"') { 4614 pGen->leaR0((int) glo, mkpCharPtr, ET_RVALUE); 4615 // This while loop merges multiple adjacent string constants. 4616 while (tok == '"') { 4617 while (ch != '"' && ch != EOF) { 4618 *allocGlobalSpace(1,1) = getq(); 4619 } 4620 if (ch != '"') { 4621 error("Unterminated string constant."); 4622 } 4623 inp(); 4624 next(); 4625 } 4626 /* Null terminate */ 4627 *glo = 0; 4628 /* align heap */ 4629 allocGlobalSpace(1,(char*) (((intptr_t) glo + 4) & -4) - glo); 4630 4631 return true; 4632 } 4633 return false; 4634 } 4635 4636 void linkGlobal(tokenid_t t, bool isFunction) { 4637 VariableInfo* pVI = VI(t); 4638 void* n = NULL; 4639 if (mpSymbolLookupFn) { 4640 n = mpSymbolLookupFn(mpSymbolLookupContext, nameof(t)); 4641 } 4642 if (pVI->pType == NULL) { 4643 if (isFunction) { 4644 pVI->pType = mkpIntFn; 4645 } else { 4646 pVI->pType = mkpInt; 4647 } 4648 } 4649 pVI->pAddress = n; 4650 } 4651 4652 void unaryOrAssignment() { 4653 unary(); 4654 if (accept('=')) { 4655 checkLVal(); 4656 pGen->pushR0(); 4657 expr(); 4658 pGen->forceR0RVal(); 4659 pGen->storeR0ToTOS(); 4660 } else if (tok == TOK_OP_ASSIGNMENT) { 4661 int t = tokc; 4662 next(); 4663 checkLVal(); 4664 pGen->pushR0(); 4665 pGen->forceR0RVal(); 4666 pGen->pushR0(); 4667 expr(); 4668 pGen->forceR0RVal(); 4669 pGen->genOp(t); 4670 pGen->storeR0ToTOS(); 4671 } 4672 } 4673 4674 /* Parse and evaluate a unary expression. 4675 */ 4676 void unary() { 4677 tokenid_t t; 4678 intptr_t a; 4679 t = 0; 4680 if (acceptStringLiteral()) { 4681 // Nothing else to do. 4682 } else { 4683 int c = tokl; 4684 a = tokc; 4685 double ad = tokd; 4686 t = tok; 4687 next(); 4688 if (t == TOK_NUM) { 4689 pGen->li(a); 4690 } else if (t == TOK_NUM_FLOAT) { 4691 // Align to 4-byte boundary 4692 glo = (char*) (((intptr_t) glo + 3) & -4); 4693 * (float*) glo = (float) ad; 4694 pGen->loadFloat((int) glo, mkpFloat); 4695 glo += 4; 4696 } else if (t == TOK_NUM_DOUBLE) { 4697 // Align to 8-byte boundary 4698 glo = (char*) (((intptr_t) glo + 7) & -8); 4699 * (double*) glo = ad; 4700 pGen->loadFloat((int) glo, mkpDouble); 4701 glo += 8; 4702 } else if (c == 2) { 4703 /* -, +, !, ~ */ 4704 unary(); 4705 pGen->forceR0RVal(); 4706 if (t == '!') 4707 pGen->gUnaryCmp(a); 4708 else if (t == '+') { 4709 // ignore unary plus. 4710 } else { 4711 pGen->genUnaryOp(a); 4712 } 4713 } else if (c == 11) { 4714 // pre increment / pre decrement 4715 unary(); 4716 doIncDec(a == OP_INCREMENT, 0); 4717 } 4718 else if (t == '(') { 4719 // It's either a cast or an expression 4720 Type* pCast = acceptCastTypeDeclaration(); 4721 if (pCast) { 4722 skip(')'); 4723 unary(); 4724 pGen->forceR0RVal(); 4725 pGen->castR0(pCast); 4726 } else { 4727 commaExpr(); 4728 skip(')'); 4729 } 4730 } else if (t == '*') { 4731 /* This is a pointer dereference. 4732 */ 4733 unary(); 4734 doPointer(); 4735 } else if (t == '&') { 4736 unary(); 4737 doAddressOf(); 4738 } else if (t == EOF ) { 4739 error("Unexpected EOF."); 4740 } else if (t == ';') { 4741 error("Unexpected ';'"); 4742 } else if (!checkSymbol(t)) { 4743 // Don't have to do anything special here, the error 4744 // message was printed by checkSymbol() above. 4745 } else { 4746 if (!isDefined(t)) { 4747 mGlobals.add(t); 4748 // printf("Adding new global function %s\n", nameof(t)); 4749 } 4750 VariableInfo* pVI = VI(t); 4751 int n = (intptr_t) pVI->pAddress; 4752 /* forward reference: try our lookup function */ 4753 if (!n) { 4754 linkGlobal(t, tok == '('); 4755 n = (intptr_t) pVI->pAddress; 4756 if (!n && tok != '(') { 4757 error("Undeclared variable %s", nameof(t)); 4758 } 4759 } 4760 if (tok != '(') { 4761 /* variable or function name */ 4762 if (!n) { 4763 linkGlobal(t, false); 4764 n = (intptr_t) pVI->pAddress; 4765 if (!n) { 4766 error("Undeclared variable %s", nameof(t)); 4767 } 4768 } 4769 } 4770 // load a variable 4771 Type* pVal; 4772 ExpressionType et; 4773 if (pVI->pType->tag == TY_ARRAY) { 4774 pVal = pVI->pType; 4775 et = ET_RVALUE; 4776 } else { 4777 pVal = createPtrType(pVI->pType); 4778 et = ET_LVALUE; 4779 } 4780 if (n) { 4781 int tag = pVal->pHead->tag; 4782 if (tag == TY_FUNC) { 4783 et = ET_RVALUE; 4784 } 4785 pGen->leaR0(n, pVal, et); 4786 } else { 4787 pVI->pForward = (void*) pGen->leaForward( 4788 (int) pVI->pForward, pVal); 4789 } 4790 } 4791 } 4792 4793 /* Now handle postfix operators */ 4794 for(;;) { 4795 if (tokl == 11) { 4796 // post inc / post dec 4797 doIncDec(tokc == OP_INCREMENT, true); 4798 next(); 4799 } else if (accept('[')) { 4800 // Array reference 4801 pGen->forceR0RVal(); 4802 pGen->pushR0(); 4803 commaExpr(); 4804 pGen->forceR0RVal(); 4805 pGen->genOp(OP_PLUS); 4806 doPointer(); 4807 skip(']'); 4808 } else if (accept('.')) { 4809 // struct element 4810 pGen->forceR0RVal(); 4811 Type* pStruct = pGen->getR0Type(); 4812 if (pStruct->tag == TY_STRUCT) { 4813 doStructMember(pStruct, true); 4814 } else { 4815 error("expected a struct value to the left of '.'"); 4816 } 4817 } else if (accept(TOK_OP_ARROW)) { 4818 pGen->forceR0RVal(); 4819 Type* pPtr = pGen->getR0Type(); 4820 if (pPtr->tag == TY_POINTER && pPtr->pHead->tag == TY_STRUCT) { 4821 pGen->loadR0FromR0(); 4822 doStructMember(pPtr->pHead, false); 4823 } else { 4824 error("Expected a pointer to a struct to the left of '->'"); 4825 } 4826 } else if (accept('(')) { 4827 /* function call */ 4828 Type* pDecl = NULL; 4829 VariableInfo* pVI = NULL; 4830 Type* pFn = pGen->getR0Type(); 4831 if (pFn->tag == TY_POINTER && pFn->pHead->tag == TY_FUNC) { 4832 pDecl = pFn->pHead; 4833 pGen->pushR0(); 4834 Type* pArgList = pDecl->pTail; 4835 bool varArgs = pArgList == NULL; 4836 /* push args and invert order */ 4837 a = pGen->beginFunctionCallArguments(); 4838 int l = 0; 4839 int argCount = 0; 4840 while (tok != ')' && tok != EOF) { 4841 if (! varArgs && !pArgList) { 4842 error("Unexpected argument."); 4843 } 4844 expr(); 4845 pGen->forceR0RVal(); 4846 Type* pTargetType; 4847 if (pArgList) { 4848 pTargetType = pArgList->pHead; 4849 pArgList = pArgList->pTail; 4850 } else { 4851 // This is a ... function, just pass arguments in their 4852 // natural type. 4853 pTargetType = pGen->getR0Type(); 4854 if (pTargetType->tag == TY_FLOAT) { 4855 pTargetType = mkpDouble; 4856 } else if (pTargetType->tag == TY_ARRAY) { 4857 // Pass arrays by pointer. 4858 pTargetType = pTargetType->pTail; 4859 } 4860 } 4861 if (pTargetType->tag == TY_VOID) { 4862 error("Can't pass void value for argument %d", 4863 argCount + 1); 4864 } else { 4865 l += pGen->storeR0ToArg(l, pTargetType); 4866 } 4867 if (accept(',')) { 4868 // fine 4869 } else if ( tok != ')') { 4870 error("Expected ',' or ')'"); 4871 } 4872 argCount += 1; 4873 } 4874 if (! varArgs && pArgList) { 4875 error("Expected more argument(s). Saw %d", argCount); 4876 } 4877 pGen->endFunctionCallArguments(pDecl, a, l); 4878 skip(')'); 4879 pGen->callIndirect(l, pDecl); 4880 pGen->adjustStackAfterCall(pDecl, l, true); 4881 } else { 4882 error("Expected a function value to left of '('."); 4883 } 4884 } else { 4885 break; 4886 } 4887 } 4888 } 4889 4890 void doStructMember(Type* pStruct, bool isDot) { 4891 Type* pStructElement = lookupStructMember(pStruct, tok); 4892 if (pStructElement) { 4893 next(); 4894 pGen->addStructOffsetR0(pStructElement->length, createPtrType(pStructElement->pHead)); 4895 } else { 4896 String buf; 4897 decodeToken(buf, tok, true); 4898 error("Expected a struct member to the right of '%s', got %s", 4899 isDot ? "." : "->", buf.getUnwrapped()); 4900 } 4901 } 4902 4903 void doIncDec(int isInc, int isPost) { 4904 // R0 already has the lval 4905 checkLVal(); 4906 int lit = isInc ? 1 : -1; 4907 pGen->pushR0(); 4908 pGen->loadR0FromR0(); 4909 int tag = pGen->getR0Type()->tag; 4910 if (!(tag == TY_INT || tag == TY_SHORT || tag == TY_CHAR || 4911 tag == TY_POINTER)) { 4912 error("++/-- illegal for this type. %d", tag); 4913 } 4914 if (isPost) { 4915 pGen->over(); 4916 pGen->pushR0(); 4917 pGen->li(lit); 4918 pGen->genOp(OP_PLUS); 4919 pGen->storeR0ToTOS(); 4920 pGen->popR0(); 4921 } else { 4922 pGen->pushR0(); 4923 pGen->li(lit); 4924 pGen->genOp(OP_PLUS); 4925 pGen->over(); 4926 pGen->storeR0ToTOS(); 4927 pGen->popR0(); 4928 } 4929 } 4930 4931 void doPointer() { 4932 pGen->forceR0RVal(); 4933 Type* pR0Type = pGen->getR0Type(); 4934 if (pR0Type->tag != TY_POINTER) { 4935 error("Expected a pointer type."); 4936 } else { 4937 if (pR0Type->pHead->tag != TY_FUNC) { 4938 pGen->setR0ExpressionType(ET_LVALUE); 4939 } 4940 } 4941 } 4942 4943 void doAddressOf() { 4944 Type* pR0 = pGen->getR0Type(); 4945 bool isFuncPtr = pR0->tag == TY_POINTER && pR0->pHead->tag == TY_FUNC; 4946 if ((! isFuncPtr) && pGen->getR0ExpressionType() != ET_LVALUE) { 4947 error("Expected an lvalue"); 4948 } 4949 Type* pR0Type = pGen->getR0Type(); 4950 pGen->setR0ExpressionType(ET_RVALUE); 4951 } 4952 4953 /* Recursive descent parser for binary operations. 4954 */ 4955 void binaryOp(int level) { 4956 intptr_t t, a; 4957 t = 0; 4958 if (level-- == 1) 4959 unaryOrAssignment(); 4960 else { 4961 binaryOp(level); 4962 a = 0; 4963 while (level == tokl) { 4964 t = tokc; 4965 next(); 4966 pGen->forceR0RVal(); 4967 if (level > 8) { 4968 a = pGen->gtst(t == OP_LOGICAL_OR, a); /* && and || output code generation */ 4969 binaryOp(level); 4970 } else { 4971 pGen->pushR0(); 4972 binaryOp(level); 4973 // Check for syntax error. 4974 if (pGen->getR0Type() == NULL) { 4975 // We failed to parse a right-hand argument. 4976 // Push a dummy value so we don't fail 4977 pGen->li(0); 4978 } 4979 pGen->forceR0RVal(); 4980 if ((level == 4) | (level == 5)) { 4981 pGen->gcmp(t); 4982 } else { 4983 pGen->genOp(t); 4984 } 4985 } 4986 } 4987 /* && and || output code generation */ 4988 if (a && level > 8) { 4989 pGen->forceR0RVal(); 4990 a = pGen->gtst(t == OP_LOGICAL_OR, a); 4991 pGen->li(t != OP_LOGICAL_OR); 4992 int b = pGen->gjmp(0); 4993 pGen->gsym(a); 4994 pGen->li(t == OP_LOGICAL_OR); 4995 pGen->gsym(b); 4996 } 4997 } 4998 } 4999 5000 void commaExpr() { 5001 for(;;) { 5002 expr(); 5003 if (!accept(',')) { 5004 break; 5005 } 5006 } 5007 } 5008 5009 void expr() { 5010 binaryOp(11); 5011 } 5012 5013 int test_expr() { 5014 commaExpr(); 5015 pGen->forceR0RVal(); 5016 return pGen->gtst(0, 0); 5017 } 5018 5019 void block(intptr_t* breakLabel, intptr_t continueAddress, bool outermostFunctionBlock) { 5020 intptr_t a, n, t; 5021 5022 Type* pBaseType; 5023 if ((pBaseType = acceptPrimitiveType(true))) { 5024 /* declarations */ 5025 localDeclarations(pBaseType); 5026 } else if (tok == TOK_IF) { 5027 next(); 5028 skip('('); 5029 a = test_expr(); 5030 skip(')'); 5031 block(breakLabel, continueAddress, false); 5032 if (tok == TOK_ELSE) { 5033 next(); 5034 n = pGen->gjmp(0); /* jmp */ 5035 pGen->gsym(a); 5036 block(breakLabel, continueAddress, false); 5037 pGen->gsym(n); /* patch else jmp */ 5038 } else { 5039 pGen->gsym(a); /* patch if test */ 5040 } 5041 } else if ((tok == TOK_WHILE) | (tok == TOK_FOR)) { 5042 t = tok; 5043 next(); 5044 skip('('); 5045 if (t == TOK_WHILE) { 5046 n = pCodeBuf->getPC(); // top of loop, target of "next" iteration 5047 a = test_expr(); 5048 } else { 5049 if (tok != ';') 5050 commaExpr(); 5051 skip(';'); 5052 n = pCodeBuf->getPC(); 5053 a = 0; 5054 if (tok != ';') 5055 a = test_expr(); 5056 skip(';'); 5057 if (tok != ')') { 5058 t = pGen->gjmp(0); 5059 commaExpr(); 5060 pGen->gjmp(n - pCodeBuf->getPC() - pGen->jumpOffset()); 5061 pGen->gsym(t); 5062 n = t + 4; 5063 } 5064 } 5065 skip(')'); 5066 block(&a, n, false); 5067 pGen->gjmp(n - pCodeBuf->getPC() - pGen->jumpOffset()); /* jmp */ 5068 pGen->gsym(a); 5069 } else if (tok == '{') { 5070 if (! outermostFunctionBlock) { 5071 mLocals.pushLevel(); 5072 } 5073 next(); 5074 while (tok != '}' && tok != EOF) 5075 block(breakLabel, continueAddress, false); 5076 skip('}'); 5077 if (! outermostFunctionBlock) { 5078 mLocals.popLevel(); 5079 } 5080 } else { 5081 if (accept(TOK_RETURN)) { 5082 if (tok != ';') { 5083 commaExpr(); 5084 pGen->forceR0RVal(); 5085 if (pReturnType->tag == TY_VOID) { 5086 error("Must not return a value from a void function"); 5087 } else { 5088 pGen->convertR0(pReturnType); 5089 } 5090 } else { 5091 if (pReturnType->tag != TY_VOID) { 5092 error("Must specify a value here"); 5093 } 5094 } 5095 rsym = pGen->gjmp(rsym); /* jmp */ 5096 } else if (accept(TOK_BREAK)) { 5097 if (breakLabel) { 5098 *breakLabel = pGen->gjmp(*breakLabel); 5099 } else { 5100 error("break statement must be within a for, do, while, or switch statement"); 5101 } 5102 } else if (accept(TOK_CONTINUE)) { 5103 if (continueAddress) { 5104 pGen->gjmp(continueAddress - pCodeBuf->getPC() - pGen->jumpOffset()); 5105 } else { 5106 error("continue statement must be within a for, do, or while statement"); 5107 } 5108 } else if (tok != ';') 5109 commaExpr(); 5110 skip(';'); 5111 } 5112 } 5113 5114 static bool typeEqual(Type* a, Type* b) { 5115 if (a == b) { 5116 return true; 5117 } 5118 if (a == NULL || b == NULL) { 5119 return false; 5120 } 5121 TypeTag at = a->tag; 5122 if (at != b->tag) { 5123 return false; 5124 } 5125 if (at == TY_POINTER) { 5126 return typeEqual(a->pHead, b->pHead); 5127 } else if (at == TY_ARRAY) { 5128 return a->length == b->length && typeEqual(a->pHead, b->pHead); 5129 } else if (at == TY_FUNC || at == TY_PARAM) { 5130 return typeEqual(a->pHead, b->pHead) 5131 && typeEqual(a->pTail, b->pTail); 5132 } else if (at == TY_STRUCT) { 5133 return a->pHead == b->pHead; 5134 } 5135 return true; 5136 } 5137 5138 Type* createType(TypeTag tag, Type* pHead, Type* pTail) { 5139 assert(tag >= TY_UNKNOWN && tag <= TY_PARAM); 5140 Type* pType = (Type*) mpCurrentArena->alloc(sizeof(Type)); 5141 memset(pType, 0, sizeof(*pType)); 5142 pType->storageClass = SC_DEFAULT; 5143 pType->tag = tag; 5144 pType->pHead = pHead; 5145 pType->pTail = pTail; 5146 return pType; 5147 } 5148 5149 Type* createPtrType(Type* pType) { 5150 return createType(TY_POINTER, pType, NULL); 5151 } 5152 5153 /** 5154 * Try to print a type in declaration order 5155 */ 5156 void decodeType(String& buffer, Type* pType) { 5157 buffer.clear(); 5158 if (pType == NULL) { 5159 buffer.appendCStr("null"); 5160 return; 5161 } 5162 decodeTypeImp(buffer, pType); 5163 } 5164 5165 void decodeTypeImp(String& buffer, Type* pType) { 5166 decodeTypeImpPrefix(buffer, pType); 5167 decodeId(buffer, pType->id); 5168 decodeTypeImpPostfix(buffer, pType); 5169 } 5170 5171 void decodeId(String& buffer, tokenid_t id) { 5172 if (id) { 5173 String temp; 5174 decodeToken(temp, id, false); 5175 buffer.append(temp); 5176 } 5177 } 5178 5179 void decodeTypeImpPrefix(String& buffer, Type* pType) { 5180 TypeTag tag = pType->tag; 5181 5182 if ((tag >= TY_INT && tag <= TY_DOUBLE) || tag == TY_STRUCT) { 5183 switch (tag) { 5184 case TY_INT: 5185 buffer.appendCStr("int"); 5186 break; 5187 case TY_SHORT: 5188 buffer.appendCStr("short"); 5189 break; 5190 case TY_CHAR: 5191 buffer.appendCStr("char"); 5192 break; 5193 case TY_VOID: 5194 buffer.appendCStr("void"); 5195 break; 5196 case TY_FLOAT: 5197 buffer.appendCStr("float"); 5198 break; 5199 case TY_DOUBLE: 5200 buffer.appendCStr("double"); 5201 break; 5202 case TY_STRUCT: 5203 { 5204 bool isStruct = (pType->pHead->alignment & 0x80000000) != 0; 5205 buffer.appendCStr(isStruct ? "struct" : "union"); 5206 if (pType->pHead && pType->pHead->structTag) { 5207 buffer.append(' '); 5208 decodeId(buffer, pType->pHead->structTag); 5209 } 5210 } 5211 break; 5212 default: 5213 break; 5214 } 5215 buffer.append(' '); 5216 } 5217 5218 switch (tag) { 5219 case TY_INT: 5220 break; 5221 case TY_SHORT: 5222 break; 5223 case TY_CHAR: 5224 break; 5225 case TY_VOID: 5226 break; 5227 case TY_FLOAT: 5228 break; 5229 case TY_DOUBLE: 5230 break; 5231 case TY_POINTER: 5232 decodeTypeImpPrefix(buffer, pType->pHead); 5233 if(pType->pHead && pType->pHead->tag == TY_FUNC) { 5234 buffer.append('('); 5235 } 5236 buffer.append('*'); 5237 break; 5238 case TY_ARRAY: 5239 decodeTypeImpPrefix(buffer, pType->pHead); 5240 break; 5241 case TY_STRUCT: 5242 break; 5243 case TY_FUNC: 5244 decodeTypeImp(buffer, pType->pHead); 5245 break; 5246 case TY_PARAM: 5247 decodeTypeImp(buffer, pType->pHead); 5248 break; 5249 default: 5250 String temp; 5251 temp.printf("Unknown tag %d", pType->tag); 5252 buffer.append(temp); 5253 break; 5254 } 5255 } 5256 5257 void decodeTypeImpPostfix(String& buffer, Type* pType) { 5258 TypeTag tag = pType->tag; 5259 5260 switch(tag) { 5261 case TY_POINTER: 5262 if(pType->pHead && pType->pHead->tag == TY_FUNC) { 5263 buffer.append(')'); 5264 } 5265 decodeTypeImpPostfix(buffer, pType->pHead); 5266 break; 5267 case TY_ARRAY: 5268 { 5269 String temp; 5270 temp.printf("[%d]", pType->length); 5271 buffer.append(temp); 5272 } 5273 break; 5274 case TY_STRUCT: 5275 if (pType->pHead->length >= 0) { 5276 buffer.appendCStr(" {"); 5277 for(Type* pArg = pType->pTail; pArg; pArg = pArg->pTail) { 5278 decodeTypeImp(buffer, pArg->pHead); 5279 buffer.appendCStr(";"); 5280 } 5281 buffer.append('}'); 5282 } 5283 break; 5284 case TY_FUNC: 5285 buffer.append('('); 5286 for(Type* pArg = pType->pTail; pArg; pArg = pArg->pTail) { 5287 decodeTypeImp(buffer, pArg); 5288 if (pArg->pTail) { 5289 buffer.appendCStr(", "); 5290 } 5291 } 5292 buffer.append(')'); 5293 break; 5294 default: 5295 break; 5296 } 5297 } 5298 5299 void printType(Type* pType) { 5300 String buffer; 5301 decodeType(buffer, pType); 5302 fprintf(stderr, "%s\n", buffer.getUnwrapped()); 5303 } 5304 5305 void insertTypeSpecifier(Type** ppType, TypeTag tag) { 5306 if (! *ppType) { 5307 *ppType = createType(tag, NULL, NULL); 5308 } else { 5309 if ((*ppType)->tag != TY_UNKNOWN) { 5310 error("Only one type specifier allowed."); 5311 } else { 5312 (*ppType)->tag = tag; 5313 } 5314 } 5315 } 5316 5317 void insertStorageClass(Type** ppType, StorageClass storageClass) { 5318 if (! *ppType) { 5319 *ppType = createType(TY_UNKNOWN, NULL, NULL); 5320 } 5321 if ((*ppType)->storageClass != SC_DEFAULT) { 5322 error("Only one storage class allowed."); 5323 } else { 5324 (*ppType)->storageClass = storageClass; 5325 } 5326 } 5327 5328 Type* acceptPrimitiveType(bool allowStorageClass) { 5329 Type* pType = NULL; 5330 for (bool keepGoing = true; keepGoing;) { 5331 switch(tok) { 5332 case TOK_AUTO: 5333 insertStorageClass(&pType, SC_AUTO); 5334 break; 5335 case TOK_REGISTER: 5336 insertStorageClass(&pType, SC_REGISTER); 5337 break; 5338 case TOK_STATIC: 5339 insertStorageClass(&pType, SC_STATIC); 5340 break; 5341 case TOK_EXTERN: 5342 insertStorageClass(&pType, SC_EXTERN); 5343 break; 5344 case TOK_TYPEDEF: 5345 insertStorageClass(&pType, SC_TYPEDEF); 5346 break; 5347 case TOK_INT: 5348 insertTypeSpecifier(&pType, TY_INT); 5349 break; 5350 case TOK_SHORT: 5351 insertTypeSpecifier(&pType, TY_SHORT); 5352 break; 5353 case TOK_CHAR: 5354 insertTypeSpecifier(&pType, TY_CHAR); 5355 break; 5356 case TOK_VOID: 5357 insertTypeSpecifier(&pType, TY_VOID); 5358 break; 5359 case TOK_FLOAT: 5360 insertTypeSpecifier(&pType, TY_FLOAT); 5361 break; 5362 case TOK_DOUBLE: 5363 insertTypeSpecifier(&pType, TY_DOUBLE); 5364 break; 5365 case TOK_STRUCT: 5366 case TOK_UNION: 5367 { 5368 insertTypeSpecifier(&pType, TY_STRUCT); 5369 bool isStruct = (tok == TOK_STRUCT); 5370 next(); 5371 pType = acceptStruct(pType, isStruct); 5372 keepGoing = false; 5373 } 5374 break; 5375 default: 5376 // Is it a typedef? 5377 if (isSymbol(tok)) { 5378 VariableInfo* pV = VI(tok); 5379 if (pV && pV->pType->storageClass == SC_TYPEDEF) { 5380 if (! pType) { 5381 pType = createType(TY_UNKNOWN, NULL, NULL); 5382 } 5383 StorageClass storageClass = pType->storageClass; 5384 *pType = *pV->pType; 5385 pType->storageClass = storageClass; 5386 } else { 5387 keepGoing = false; 5388 } 5389 } else { 5390 keepGoing = false; 5391 } 5392 } 5393 if (keepGoing) { 5394 next(); 5395 } 5396 } 5397 if (pType) { 5398 if (pType->tag == TY_UNKNOWN) { 5399 pType->tag = TY_INT; 5400 } 5401 if (allowStorageClass) { 5402 switch(pType->storageClass) { 5403 case SC_AUTO: error("auto not supported."); break; 5404 case SC_REGISTER: error("register not supported."); break; 5405 case SC_STATIC: error("static not supported."); break; 5406 case SC_EXTERN: error("extern not supported."); break; 5407 default: break; 5408 } 5409 } else { 5410 if (pType->storageClass != SC_DEFAULT) { 5411 error("An explicit storage class is not allowed in this type declaration"); 5412 } 5413 } 5414 } 5415 return pType; 5416 } 5417 5418 Type* acceptStruct(Type* pStructType, bool isStruct) { 5419 tokenid_t structTag = acceptSymbol(); 5420 bool isDeclaration = accept('{'); 5421 bool fail = false; 5422 5423 if (structTag) { 5424 Token* pToken = &mTokenTable[structTag]; 5425 VariableInfo* pStructInfo = pToken->mpStructInfo; 5426 bool needToDeclare = !pStructInfo; 5427 if (pStructInfo) { 5428 if (isDeclaration) { 5429 if (mpCurrentSymbolStack->isStructTagDefinedAtCurrentLevel(structTag)) { 5430 if (pStructInfo->pType->pHead->length == -1) { 5431 // we're filling in a forward declaration. 5432 needToDeclare = false; 5433 } else { 5434 error("A struct with the same name is already defined at this level."); 5435 fail = true; 5436 } 5437 } else { 5438 needToDeclare = true; 5439 } 5440 } 5441 if (!fail) { 5442 assert(pStructInfo->isStructTag); 5443 pStructType->pHead = pStructInfo->pType; 5444 pStructType->pTail = pStructType->pHead->pTail; 5445 } 5446 } 5447 5448 if (needToDeclare) { 5449 // This is a new struct name 5450 pToken->mpStructInfo = mpCurrentSymbolStack->addStructTag(structTag); 5451 StorageClass storageClass = pStructType->storageClass; 5452 pStructType = createType(TY_STRUCT, NULL, NULL); 5453 pStructType->structTag = structTag; 5454 pStructType->pHead = pStructType; 5455 pStructType->storageClass = storageClass; 5456 if (! isDeclaration) { 5457 // A forward declaration 5458 pStructType->length = -1; 5459 } 5460 pToken->mpStructInfo->pType = pStructType; 5461 } 5462 } else { 5463 // An anonymous struct 5464 pStructType->pHead = pStructType; 5465 } 5466 5467 if (isDeclaration) { 5468 size_t offset = 0; 5469 size_t structSize = 0; 5470 size_t structAlignment = 0; 5471 Type** pParamHolder = & pStructType->pHead->pTail; 5472 while (tok != '}' && tok != EOF) { 5473 Type* pPrimitiveType = expectPrimitiveType(false); 5474 if (pPrimitiveType) { 5475 while (tok != ';' && tok != EOF) { 5476 Type* pItem = acceptDeclaration(pPrimitiveType, true, false); 5477 if (!pItem) { 5478 break; 5479 } 5480 if (lookupStructMember(pStructType, pItem->id)) { 5481 String buf; 5482 decodeToken(buf, pItem->id, false); 5483 error("Duplicate struct member %s", buf.getUnwrapped()); 5484 } 5485 Type* pStructElement = createType(TY_PARAM, pItem, NULL); 5486 size_t alignment = pGen->alignmentOf(pItem); 5487 if (alignment > structAlignment) { 5488 structAlignment = alignment; 5489 } 5490 size_t alignmentMask = alignment - 1; 5491 offset = (offset + alignmentMask) & ~alignmentMask; 5492 pStructElement->length = offset; 5493 size_t size = pGen->sizeOf(pItem); 5494 if (isStruct) { 5495 offset += size; 5496 structSize = offset; 5497 } else { 5498 if (size >= structSize) { 5499 structSize = size; 5500 } 5501 } 5502 *pParamHolder = pStructElement; 5503 pParamHolder = &pStructElement->pTail; 5504 accept(','); 5505 } 5506 skip(';'); 5507 } else { 5508 // Some sort of syntax error, skip token and keep trying 5509 next(); 5510 } 5511 } 5512 if (!fail) { 5513 pStructType->pHead->length = structSize; 5514 pStructType->pHead->alignment = structAlignment | (isStruct << 31); 5515 } 5516 skip('}'); 5517 } 5518 if (fail) { 5519 pStructType = NULL; 5520 } 5521 return pStructType; 5522 } 5523 5524 Type* lookupStructMember(Type* pStruct, tokenid_t memberId) { 5525 for(Type* pStructElement = pStruct->pHead->pTail; pStructElement; pStructElement = pStructElement->pTail) { 5526 if (pStructElement->pHead->id == memberId) { 5527 return pStructElement; 5528 } 5529 } 5530 return NULL; 5531 } 5532 5533 Type* acceptDeclaration(Type* pType, bool nameAllowed, bool nameRequired) { 5534 tokenid_t declName = 0; 5535 bool reportFailure = false; 5536 StorageClass storageClass = pType->storageClass; 5537 pType = acceptDecl2(pType, declName, nameAllowed, 5538 nameRequired, reportFailure); 5539 if (declName) { 5540 // Clone the parent type so we can set a unique ID 5541 Type* pOldType = pType; 5542 pType = createType(pType->tag, pType->pHead, pType->pTail); 5543 *pType = *pOldType; 5544 pType->id = declName; 5545 pType->storageClass = storageClass; 5546 } else if (nameRequired) { 5547 error("Expected a variable name"); 5548 } 5549 #if 0 5550 fprintf(stderr, "Parsed a declaration: "); 5551 printType(pType); 5552 #endif 5553 if (reportFailure) { 5554 return NULL; 5555 } 5556 return pType; 5557 } 5558 5559 Type* expectDeclaration(Type* pBaseType) { 5560 bool nameRequired = pBaseType->tag != TY_STRUCT; 5561 Type* pType = acceptDeclaration(pBaseType, true, nameRequired); 5562 if (! pType) { 5563 error("Expected a declaration"); 5564 } 5565 return pType; 5566 } 5567 5568 /* Used for accepting types that appear in casts */ 5569 Type* acceptCastTypeDeclaration() { 5570 Type* pType = acceptPrimitiveType(false); 5571 if (pType) { 5572 pType = acceptDeclaration(pType, false, false); 5573 } 5574 return pType; 5575 } 5576 5577 Type* expectCastTypeDeclaration() { 5578 Type* pType = acceptCastTypeDeclaration(); 5579 if (! pType) { 5580 error("Expected a declaration"); 5581 } 5582 return pType; 5583 } 5584 5585 Type* acceptDecl2(Type* pType, tokenid_t& declName, 5586 bool nameAllowed, bool nameRequired, 5587 bool& reportFailure) { 5588 while (accept('*')) { 5589 pType = createType(TY_POINTER, pType, NULL); 5590 } 5591 pType = acceptDecl3(pType, declName, nameAllowed, nameRequired, 5592 reportFailure); 5593 return pType; 5594 } 5595 5596 Type* acceptDecl3(Type* pType, tokenid_t& declName, 5597 bool nameAllowed, bool nameRequired, 5598 bool& reportFailure) { 5599 // direct-dcl : 5600 // name 5601 // (dcl) 5602 // direct-dcl() 5603 // direct-dcl[] 5604 Type* pNewHead = NULL; 5605 if (accept('(')) { 5606 pNewHead = acceptDecl2(pNewHead, declName, nameAllowed, 5607 nameRequired, reportFailure); 5608 skip(')'); 5609 } else if ((declName = acceptSymbol()) != 0) { 5610 if (nameAllowed == false && declName) { 5611 error("Symbol %s not allowed here", nameof(declName)); 5612 reportFailure = true; 5613 } 5614 } else if (nameRequired && ! declName) { 5615 String temp; 5616 decodeToken(temp, tok, true); 5617 error("Expected name. Got %s", temp.getUnwrapped()); 5618 reportFailure = true; 5619 } 5620 for(;;) { 5621 if (accept('(')) { 5622 // Function declaration 5623 Type* pTail = acceptArgs(nameAllowed); 5624 pType = createType(TY_FUNC, pType, pTail); 5625 skip(')'); 5626 } if (accept('[')) { 5627 if (tok != ']') { 5628 if (tok != TOK_NUM || tokc <= 0) { 5629 error("Expected positive integer constant"); 5630 } else { 5631 Type* pDecayType = createPtrType(pType); 5632 pType = createType(TY_ARRAY, pType, pDecayType); 5633 pType->length = tokc; 5634 } 5635 next(); 5636 } 5637 skip(']'); 5638 } else { 5639 break; 5640 } 5641 } 5642 5643 if (pNewHead) { 5644 Type* pA = pNewHead; 5645 while (pA->pHead) { 5646 pA = pA->pHead; 5647 } 5648 pA->pHead = pType; 5649 pType = pNewHead; 5650 } 5651 return pType; 5652 } 5653 5654 Type* acceptArgs(bool nameAllowed) { 5655 Type* pHead = NULL; 5656 Type* pTail = NULL; 5657 for(;;) { 5658 Type* pBaseArg = acceptPrimitiveType(false); 5659 if (pBaseArg) { 5660 Type* pArg = acceptDeclaration(pBaseArg, nameAllowed, false); 5661 if (pArg) { 5662 Type* pParam = createType(TY_PARAM, pArg, NULL); 5663 if (!pHead) { 5664 pHead = pParam; 5665 pTail = pParam; 5666 } else { 5667 pTail->pTail = pParam; 5668 pTail = pParam; 5669 } 5670 } 5671 } 5672 if (! accept(',')) { 5673 break; 5674 } 5675 } 5676 return pHead; 5677 } 5678 5679 Type* expectPrimitiveType(bool allowStorageClass) { 5680 Type* pType = acceptPrimitiveType(allowStorageClass); 5681 if (!pType) { 5682 String buf; 5683 decodeToken(buf, tok, true); 5684 error("Expected a type, got %s", buf.getUnwrapped()); 5685 } 5686 return pType; 5687 } 5688 5689 void checkLVal() { 5690 if (pGen->getR0ExpressionType() != ET_LVALUE) { 5691 error("Expected an lvalue"); 5692 } 5693 } 5694 5695 void addGlobalSymbol(Type* pDecl) { 5696 tokenid_t t = pDecl->id; 5697 VariableInfo* pVI = VI(t); 5698 if(pVI && pVI->pAddress) { 5699 reportDuplicate(t); 5700 } 5701 mGlobals.add(pDecl); 5702 } 5703 5704 void reportDuplicate(tokenid_t t) { 5705 error("Duplicate definition of %s", nameof(t)); 5706 } 5707 5708 void addLocalSymbol(Type* pDecl) { 5709 tokenid_t t = pDecl->id; 5710 if (mLocals.isDefinedAtCurrentLevel(t)) { 5711 reportDuplicate(t); 5712 } 5713 mLocals.add(pDecl); 5714 } 5715 5716 bool checkUndeclaredStruct(Type* pBaseType) { 5717 if (pBaseType->tag == TY_STRUCT && pBaseType->length < 0) { 5718 String temp; 5719 decodeToken(temp, pBaseType->structTag, false); 5720 error("Undeclared struct %s", temp.getUnwrapped()); 5721 return true; 5722 } 5723 return false; 5724 } 5725 5726 void localDeclarations(Type* pBaseType) { 5727 intptr_t a; 5728 5729 while (pBaseType) { 5730 while (tok != ';' && tok != EOF) { 5731 Type* pDecl = expectDeclaration(pBaseType); 5732 if (!pDecl) { 5733 break; 5734 } 5735 if (!pDecl->id) { 5736 break; 5737 } 5738 if (checkUndeclaredStruct(pDecl)) { 5739 break; 5740 } 5741 addLocalSymbol(pDecl); 5742 if (pDecl->tag == TY_FUNC) { 5743 if (tok == '{') { 5744 error("Nested functions are not allowed. Did you forget a '}' ?"); 5745 break; 5746 } 5747 // Else it's a forward declaration of a function. 5748 } else if (pDecl->storageClass != SC_TYPEDEF) { 5749 int variableAddress = 0; 5750 size_t alignment = pGen->alignmentOf(pDecl); 5751 assert(alignment > 0); 5752 size_t alignmentMask = ~ (alignment - 1); 5753 size_t sizeOf = pGen->sizeOf(pDecl); 5754 assert(sizeOf > 0); 5755 loc = (loc + alignment - 1) & alignmentMask; 5756 size_t alignedSize = (sizeOf + alignment - 1) & alignmentMask; 5757 loc = loc + alignedSize; 5758 variableAddress = -loc; 5759 VI(pDecl->id)->pAddress = (void*) variableAddress; 5760 if (accept('=')) { 5761 /* assignment */ 5762 pGen->leaR0(variableAddress, createPtrType(pDecl), ET_LVALUE); 5763 pGen->pushR0(); 5764 expr(); 5765 pGen->forceR0RVal(); 5766 pGen->storeR0ToTOS(); 5767 } 5768 } 5769 if (tok == ',') 5770 next(); 5771 } 5772 skip(';'); 5773 pBaseType = acceptPrimitiveType(true); 5774 } 5775 } 5776 5777 bool checkSymbol() { 5778 return checkSymbol(tok); 5779 } 5780 5781 void decodeToken(String& buffer, tokenid_t token, bool quote) { 5782 if (token == EOF ) { 5783 buffer.printf("EOF"); 5784 } else if (token == TOK_NUM) { 5785 buffer.printf("numeric constant %d(0x%x)", tokc, tokc); 5786 } else if (token == TOK_NUM_FLOAT) { 5787 buffer.printf("numeric constant float %g", tokd); 5788 } else if (token == TOK_NUM_DOUBLE) { 5789 buffer.printf("numeric constant double %g", tokd); 5790 } else if (token >= 0 && token < 256) { 5791 if (token < 32) { 5792 buffer.printf("'\\x%02x'", token); 5793 } else { 5794 buffer.printf("'%c'", token); 5795 } 5796 } else { 5797 if (quote) { 5798 if (token >= TOK_KEYWORD && token < TOK_SYMBOL) { 5799 buffer.printf("keyword \"%s\"", nameof(token)); 5800 } else { 5801 buffer.printf("symbol \"%s\"", nameof(token)); 5802 } 5803 } else { 5804 buffer.printf("%s", nameof(token)); 5805 } 5806 } 5807 } 5808 5809 void printToken(tokenid_t token) { 5810 String buffer; 5811 decodeToken(buffer, token, true); 5812 fprintf(stderr, "%s\n", buffer.getUnwrapped()); 5813 } 5814 5815 bool checkSymbol(tokenid_t token) { 5816 bool result = token >= TOK_SYMBOL; 5817 if (!result) { 5818 String temp; 5819 decodeToken(temp, token, true); 5820 error("Expected symbol. Got %s", temp.getUnwrapped()); 5821 } 5822 return result; 5823 } 5824 5825 tokenid_t acceptSymbol() { 5826 tokenid_t result = 0; 5827 if (tok >= TOK_SYMBOL) { 5828 result = tok; 5829 next(); 5830 } 5831 return result; 5832 } 5833 5834 void globalDeclarations() { 5835 mpCurrentSymbolStack = &mGlobals; 5836 while (tok != EOF) { 5837 Type* pBaseType = expectPrimitiveType(true); 5838 if (!pBaseType) { 5839 break; 5840 } 5841 Type* pDecl = expectDeclaration(pBaseType); 5842 if (!pDecl) { 5843 break; 5844 } 5845 if (!pDecl->id) { 5846 skip(';'); 5847 continue; 5848 } 5849 5850 if (checkUndeclaredStruct(pDecl)) { 5851 skip(';'); 5852 continue; 5853 } 5854 if (! isDefined(pDecl->id)) { 5855 addGlobalSymbol(pDecl); 5856 } 5857 VariableInfo* name = VI(pDecl->id); 5858 if (name && name->pAddress) { 5859 error("Already defined global %s", nameof(pDecl->id)); 5860 } 5861 if (pDecl->tag < TY_FUNC) { 5862 // it's a variable declaration 5863 for(;;) { 5864 if (pDecl->storageClass == SC_TYPEDEF) { 5865 // Do not allocate storage. 5866 } else { 5867 if (name && !name->pAddress) { 5868 name->pAddress = (int*) allocGlobalSpace( 5869 pGen->alignmentOf(name->pType), 5870 pGen->sizeOf(name->pType)); 5871 } 5872 if (accept('=')) { 5873 if (tok == TOK_NUM) { 5874 if (name) { 5875 * (int*) name->pAddress = tokc; 5876 } 5877 next(); 5878 } else { 5879 error("Expected an integer constant"); 5880 } 5881 } 5882 } 5883 if (!accept(',')) { 5884 break; 5885 } 5886 pDecl = expectDeclaration(pBaseType); 5887 if (!pDecl) { 5888 break; 5889 } 5890 if (! isDefined(pDecl->id)) { 5891 addGlobalSymbol(pDecl); 5892 } 5893 name = VI(pDecl->id); 5894 } 5895 skip(';'); 5896 } else { 5897 // Function declaration 5898 if (accept(';')) { 5899 // forward declaration. 5900 } else if (tok != '{') { 5901 error("expected '{'"); 5902 } else { 5903 mpCurrentArena = &mLocalArena; 5904 mpCurrentSymbolStack = &mLocals; 5905 if (name) { 5906 /* patch forward references */ 5907 pGen->resolveForward((int) name->pForward); 5908 /* put function address */ 5909 name->pAddress = (void*) pCodeBuf->getPC(); 5910 } 5911 // Calculate stack offsets for parameters 5912 mLocals.pushLevel(); 5913 intptr_t a = 8; 5914 int argCount = 0; 5915 for (Type* pP = pDecl->pTail; pP; pP = pP->pTail) { 5916 Type* pArg = pP->pHead; 5917 if (pArg->id) { 5918 addLocalSymbol(pArg); 5919 } 5920 /* read param name and compute offset */ 5921 Type* pPassingType = passingType(pArg); 5922 size_t alignment = pGen->alignmentOf(pPassingType); 5923 a = (a + alignment - 1) & ~ (alignment-1); 5924 if (pArg->id) { 5925 VI(pArg->id)->pAddress = (void*) a; 5926 } 5927 a = a + pGen->sizeOf(pPassingType); 5928 argCount++; 5929 } 5930 rsym = loc = 0; 5931 pReturnType = pDecl->pHead; 5932 a = pGen->functionEntry(pDecl); 5933 block(0, 0, true); 5934 pGen->gsym(rsym); 5935 pGen->functionExit(pDecl, a, loc); 5936 mLocals.popLevel(); 5937 mpCurrentArena = &mGlobalArena; 5938 mpCurrentSymbolStack = &mGlobals; 5939 } 5940 } 5941 } 5942 } 5943 5944 Type* passingType(Type* pType) { 5945 switch (pType->tag) { 5946 case TY_CHAR: 5947 case TY_SHORT: 5948 return mkpInt; 5949 default: 5950 return pType; 5951 } 5952 } 5953 5954 char* allocGlobalSpace(size_t alignment, size_t bytes) { 5955 size_t base = (((size_t) glo) + alignment - 1) & ~(alignment-1); 5956 size_t end = base + bytes; 5957 if ((end - (size_t) pGlobalBase) > (size_t) ALLOC_SIZE) { 5958 error("Global space exhausted"); 5959 assert(false); 5960 return NULL; 5961 } 5962 char* result = (char*) base; 5963 glo = (char*) end; 5964 return result; 5965 } 5966 5967 void cleanup() { 5968 if (pGlobalBase != 0) { 5969 free(pGlobalBase); 5970 pGlobalBase = 0; 5971 } 5972 if (pGen) { 5973 delete pGen; 5974 pGen = 0; 5975 } 5976 if (pCodeBuf) { 5977 delete pCodeBuf; 5978 pCodeBuf = 0; 5979 } 5980 if (file) { 5981 delete file; 5982 file = 0; 5983 } 5984 } 5985 5986 // One-time initialization, when class is constructed. 5987 void init() { 5988 mpSymbolLookupFn = 0; 5989 mpSymbolLookupContext = 0; 5990 } 5991 5992 void clear() { 5993 tok = 0; 5994 tokc = 0; 5995 tokl = 0; 5996 ch = 0; 5997 rsym = 0; 5998 loc = 0; 5999 glo = 0; 6000 macroLevel = -1; 6001 file = 0; 6002 pGlobalBase = 0; 6003 pCodeBuf = 0; 6004 pGen = 0; 6005 mPragmaStringCount = 0; 6006 mCompileResult = 0; 6007 mLineNumber = 1; 6008 mbBumpLine = false; 6009 mbSuppressMacroExpansion = false; 6010 } 6011 6012 void setArchitecture(const char* architecture) { 6013 delete pGen; 6014 pGen = 0; 6015 6016 delete pCodeBuf; 6017 pCodeBuf = new CodeBuf(); 6018 6019 if (architecture != NULL) { 6020 #ifdef PROVIDE_ARM_CODEGEN 6021 if (! pGen && strcmp(architecture, "arm") == 0) { 6022 pGen = new ARMCodeGenerator(); 6023 pCodeBuf = new ARMCodeBuf(pCodeBuf); 6024 } 6025 #endif 6026 #ifdef PROVIDE_X86_CODEGEN 6027 if (! pGen && strcmp(architecture, "x86") == 0) { 6028 pGen = new X86CodeGenerator(); 6029 } 6030 #endif 6031 if (!pGen ) { 6032 error("Unknown architecture %s\n", architecture); 6033 } 6034 } 6035 6036 if (pGen == NULL) { 6037 #if defined(DEFAULT_ARM_CODEGEN) 6038 pGen = new ARMCodeGenerator(); 6039 pCodeBuf = new ARMCodeBuf(pCodeBuf); 6040 #elif defined(DEFAULT_X86_CODEGEN) 6041 pGen = new X86CodeGenerator(); 6042 #endif 6043 } 6044 if (pGen == NULL) { 6045 error("No code generator defined."); 6046 } else { 6047 pGen->setErrorSink(this); 6048 pGen->setTypes(mkpInt); 6049 } 6050 } 6051 6052 public: 6053 struct args { 6054 args() { 6055 architecture = 0; 6056 } 6057 const char* architecture; 6058 }; 6059 6060 Compiler() { 6061 init(); 6062 clear(); 6063 } 6064 6065 ~Compiler() { 6066 cleanup(); 6067 } 6068 6069 void registerSymbolCallback(ACCSymbolLookupFn pFn, ACCvoid* pContext) { 6070 mpSymbolLookupFn = pFn; 6071 mpSymbolLookupContext = pContext; 6072 } 6073 6074 int compile(const char* text, size_t textLength) { 6075 int result; 6076 6077 mpCurrentArena = &mGlobalArena; 6078 createPrimitiveTypes(); 6079 cleanup(); 6080 clear(); 6081 mTokenTable.setArena(&mGlobalArena); 6082 mGlobals.setArena(&mGlobalArena); 6083 mGlobals.setTokenTable(&mTokenTable); 6084 mLocals.setArena(&mLocalArena); 6085 mLocals.setTokenTable(&mTokenTable); 6086 6087 internKeywords(); 6088 setArchitecture(NULL); 6089 if (!pGen) { 6090 return -1; 6091 } 6092 #ifdef PROVIDE_TRACE_CODEGEN 6093 pGen = new TraceCodeGenerator(pGen); 6094 #endif 6095 pGen->setErrorSink(this); 6096 6097 if (pCodeBuf) { 6098 pCodeBuf->init(ALLOC_SIZE); 6099 } 6100 pGen->init(pCodeBuf); 6101 file = new TextInputStream(text, textLength); 6102 pGlobalBase = (char*) calloc(1, ALLOC_SIZE); 6103 glo = pGlobalBase; 6104 inp(); 6105 next(); 6106 globalDeclarations(); 6107 checkForUndefinedForwardReferences(); 6108 result = pGen->finishCompile(); 6109 if (result == 0) { 6110 if (mErrorBuf.len()) { 6111 result = -2; 6112 } 6113 } 6114 mCompileResult = result; 6115 return result; 6116 } 6117 6118 void createPrimitiveTypes() { 6119 mkpInt = createType(TY_INT, NULL, NULL); 6120 mkpShort = createType(TY_SHORT, NULL, NULL); 6121 mkpChar = createType(TY_CHAR, NULL, NULL); 6122 mkpVoid = createType(TY_VOID, NULL, NULL); 6123 mkpFloat = createType(TY_FLOAT, NULL, NULL); 6124 mkpDouble = createType(TY_DOUBLE, NULL, NULL); 6125 mkpIntFn = createType(TY_FUNC, mkpInt, NULL); 6126 mkpIntPtr = createPtrType(mkpInt); 6127 mkpCharPtr = createPtrType(mkpChar); 6128 mkpFloatPtr = createPtrType(mkpFloat); 6129 mkpDoublePtr = createPtrType(mkpDouble); 6130 mkpPtrIntFn = createPtrType(mkpIntFn); 6131 } 6132 6133 void checkForUndefinedForwardReferences() { 6134 mGlobals.forEach(static_ufrcFn, this); 6135 } 6136 6137 static bool static_ufrcFn(VariableInfo* value, void* context) { 6138 Compiler* pCompiler = (Compiler*) context; 6139 return pCompiler->undefinedForwardReferenceCheck(value); 6140 } 6141 6142 bool undefinedForwardReferenceCheck(VariableInfo* value) { 6143 if (!value->pAddress && value->pForward) { 6144 error("Undefined forward reference: %s", 6145 mTokenTable[value->tok].pText); 6146 } 6147 return true; 6148 } 6149 6150 /* Look through the symbol table to find a symbol. 6151 * If found, return its value. 6152 */ 6153 void* lookup(const char* name) { 6154 if (mCompileResult == 0) { 6155 tokenid_t tok = mTokenTable.intern(name, strlen(name)); 6156 VariableInfo* pVariableInfo = VI(tok); 6157 if (pVariableInfo) { 6158 return pVariableInfo->pAddress; 6159 } 6160 } 6161 return NULL; 6162 } 6163 6164 void getPragmas(ACCsizei* actualStringCount, 6165 ACCsizei maxStringCount, ACCchar** strings) { 6166 int stringCount = mPragmaStringCount; 6167 if (actualStringCount) { 6168 *actualStringCount = stringCount; 6169 } 6170 if (stringCount > maxStringCount) { 6171 stringCount = maxStringCount; 6172 } 6173 if (strings) { 6174 char* pPragmas = mPragmas.getUnwrapped(); 6175 while (stringCount-- > 0) { 6176 *strings++ = pPragmas; 6177 pPragmas += strlen(pPragmas) + 1; 6178 } 6179 } 6180 } 6181 6182 void getProgramBinary(ACCvoid** base, ACCsizei* length) { 6183 *base = pCodeBuf->getBase(); 6184 *length = (ACCsizei) pCodeBuf->getSize(); 6185 } 6186 6187 char* getErrorMessage() { 6188 return mErrorBuf.getUnwrapped(); 6189 } 6190 }; 6191 6192 const char* Compiler::operatorChars = 6193 "++--*@/@%@+@-@<<>><=>=<@>@==!=&&||&@^@|@~@!@"; 6194 6195 const char Compiler::operatorLevel[] = 6196 {11, 11, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 6197 5, 5, /* ==, != */ 6198 9, 10, /* &&, || */ 6199 6, 7, 8, /* & ^ | */ 6200 2, 2 /* ~ ! */ 6201 }; 6202 6203 #ifdef PROVIDE_X86_CODEGEN 6204 const int Compiler::X86CodeGenerator::operatorHelper[] = { 6205 0x1, // ++ 6206 0xff, // -- 6207 0xc1af0f, // * 6208 0xf9f79991, // / 6209 0xf9f79991, // % (With manual assist to swap results) 6210 0xc801, // + 6211 0xd8f7c829, // - 6212 0xe0d391, // << 6213 0xf8d391, // >> 6214 0xe, // <= 6215 0xd, // >= 6216 0xc, // < 6217 0xf, // > 6218 0x4, // == 6219 0x5, // != 6220 0x0, // && 6221 0x1, // || 6222 0xc821, // & 6223 0xc831, // ^ 6224 0xc809, // | 6225 0xd0f7, // ~ 6226 0x4 // ! 6227 }; 6228 #endif 6229 6230 struct ACCscript { 6231 ACCscript() { 6232 text = 0; 6233 textLength = 0; 6234 accError = ACC_NO_ERROR; 6235 } 6236 6237 ~ACCscript() { 6238 delete text; 6239 } 6240 6241 void registerSymbolCallback(ACCSymbolLookupFn pFn, ACCvoid* pContext) { 6242 compiler.registerSymbolCallback(pFn, pContext); 6243 } 6244 6245 void setError(ACCenum error) { 6246 if (accError == ACC_NO_ERROR && error != ACC_NO_ERROR) { 6247 accError = error; 6248 } 6249 } 6250 6251 ACCenum getError() { 6252 ACCenum result = accError; 6253 accError = ACC_NO_ERROR; 6254 return result; 6255 } 6256 6257 Compiler compiler; 6258 char* text; 6259 int textLength; 6260 ACCenum accError; 6261 }; 6262 6263 6264 extern "C" 6265 ACCscript* accCreateScript() { 6266 return new ACCscript(); 6267 } 6268 6269 extern "C" 6270 ACCenum accGetError( ACCscript* script ) { 6271 return script->getError(); 6272 } 6273 6274 extern "C" 6275 void accDeleteScript(ACCscript* script) { 6276 delete script; 6277 } 6278 6279 extern "C" 6280 void accRegisterSymbolCallback(ACCscript* script, ACCSymbolLookupFn pFn, 6281 ACCvoid* pContext) { 6282 script->registerSymbolCallback(pFn, pContext); 6283 } 6284 6285 extern "C" 6286 void accScriptSource(ACCscript* script, 6287 ACCsizei count, 6288 const ACCchar ** string, 6289 const ACCint * length) { 6290 int totalLength = 0; 6291 for(int i = 0; i < count; i++) { 6292 int len = -1; 6293 const ACCchar* s = string[i]; 6294 if (length) { 6295 len = length[i]; 6296 } 6297 if (len < 0) { 6298 len = strlen(s); 6299 } 6300 totalLength += len; 6301 } 6302 delete script->text; 6303 char* text = new char[totalLength + 1]; 6304 script->text = text; 6305 script->textLength = totalLength; 6306 char* dest = text; 6307 for(int i = 0; i < count; i++) { 6308 int len = -1; 6309 const ACCchar* s = string[i]; 6310 if (length) { 6311 len = length[i]; 6312 } 6313 if (len < 0) { 6314 len = strlen(s); 6315 } 6316 memcpy(dest, s, len); 6317 dest += len; 6318 } 6319 text[totalLength] = '\0'; 6320 6321 #ifdef DEBUG_SAVE_INPUT_TO_FILE 6322 LOGD("Saving input to file..."); 6323 int counter; 6324 char path[PATH_MAX]; 6325 for (counter = 0; counter < 4096; counter++) { 6326 sprintf(path, DEBUG_DUMP_PATTERN, counter); 6327 if(access(path, F_OK) != 0) { 6328 break; 6329 } 6330 } 6331 if (counter < 4096) { 6332 LOGD("Saving input to file %s", path); 6333 FILE* fd = fopen(path, "w"); 6334 if (fd) { 6335 fwrite(text, totalLength, 1, fd); 6336 fclose(fd); 6337 LOGD("Saved input to file %s", path); 6338 } else { 6339 LOGD("Could not save. errno: %d", errno); 6340 } 6341 } 6342 #endif 6343 } 6344 6345 extern "C" 6346 void accCompileScript(ACCscript* script) { 6347 int result = script->compiler.compile(script->text, script->textLength); 6348 if (result) { 6349 script->setError(ACC_INVALID_OPERATION); 6350 } 6351 } 6352 6353 extern "C" 6354 void accGetScriptiv(ACCscript* script, 6355 ACCenum pname, 6356 ACCint * params) { 6357 switch (pname) { 6358 case ACC_INFO_LOG_LENGTH: 6359 *params = 0; 6360 break; 6361 } 6362 } 6363 6364 extern "C" 6365 void accGetScriptInfoLog(ACCscript* script, 6366 ACCsizei maxLength, 6367 ACCsizei * length, 6368 ACCchar * infoLog) { 6369 char* message = script->compiler.getErrorMessage(); 6370 int messageLength = strlen(message) + 1; 6371 if (length) { 6372 *length = messageLength; 6373 } 6374 if (infoLog && maxLength > 0) { 6375 int trimmedLength = maxLength < messageLength ? 6376 maxLength : messageLength; 6377 memcpy(infoLog, message, trimmedLength); 6378 infoLog[trimmedLength] = 0; 6379 } 6380 } 6381 6382 extern "C" 6383 void accGetScriptLabel(ACCscript* script, const ACCchar * name, 6384 ACCvoid ** address) { 6385 void* value = script->compiler.lookup(name); 6386 if (value) { 6387 *address = value; 6388 } else { 6389 script->setError(ACC_INVALID_VALUE); 6390 } 6391 } 6392 6393 extern "C" 6394 void accGetPragmas(ACCscript* script, ACCsizei* actualStringCount, 6395 ACCsizei maxStringCount, ACCchar** strings){ 6396 script->compiler.getPragmas(actualStringCount, maxStringCount, strings); 6397 } 6398 6399 extern "C" 6400 void accGetProgramBinary(ACCscript* script, 6401 ACCvoid** base, ACCsizei* length) { 6402 script->compiler.getProgramBinary(base, length); 6403 } 6404 6405 6406 } // namespace acc 6407 6408