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