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