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