system/corennnnn
Revision | a8f427f60620d766b201c9a84c457fa5dbaf95d4 (tree) |
---|---|
Time | 2009-07-14 10:40:08 |
Author | Jack Palevich <jackpal@goog...> |
Commiter | Jack Palevich |
Implement pointer arithmetic.
@@ -269,6 +269,10 @@ class Compiler : public ErrorSink { | ||
269 | 269 | } |
270 | 270 | } |
271 | 271 | |
272 | + void setTypes(Type* pInt) { | |
273 | + mkpInt = pInt; | |
274 | + } | |
275 | + | |
272 | 276 | /* Emit a function prolog. |
273 | 277 | * pDecl is the function declaration, which gives the arguments. |
274 | 278 | * Save the old value of the FP. |
@@ -545,6 +549,8 @@ class Compiler : public ErrorSink { | ||
545 | 549 | return tag == TY_FLOAT || tag == TY_DOUBLE; |
546 | 550 | } |
547 | 551 | |
552 | + Type* mkpInt; | |
553 | + | |
548 | 554 | private: |
549 | 555 | Vector<Type*> mExpressionStack; |
550 | 556 | CodeBuf* pCodeBuf; |
@@ -615,18 +621,7 @@ class Compiler : public ErrorSink { | ||
615 | 621 | |
616 | 622 | /* load immediate value */ |
617 | 623 | virtual void li(int t, Type* pType) { |
618 | - LOG_API("li(%d);\n", t); | |
619 | - if (t >= 0 && t < 255) { | |
620 | - o4(0xE3A00000 + t); // mov r0, #0 | |
621 | - } else if (t >= -256 && t < 0) { | |
622 | - // mvn means move constant ^ ~0 | |
623 | - o4(0xE3E00001 - t); // mvn r0, #0 | |
624 | - } else { | |
625 | - o4(0xE51F0000); // ldr r0, .L3 | |
626 | - o4(0xEA000000); // b .L99 | |
627 | - o4(t); // .L3: .word 0 | |
628 | - // .L99: | |
629 | - } | |
624 | + liReg(t, 0); | |
630 | 625 | setR0Type(pType); |
631 | 626 | } |
632 | 627 |
@@ -774,50 +769,102 @@ class Compiler : public ErrorSink { | ||
774 | 769 | LOG_API("genOp(%d);\n", op); |
775 | 770 | Type* pR0Type = getR0Type(); |
776 | 771 | Type* pTOSType = getTOSType(); |
777 | - TypeTag tagR0 = collapseType(pR0Type->tag); | |
778 | - TypeTag tagTOS = collapseType(pTOSType->tag); | |
779 | - if (tagR0 == TY_INT && tagTOS == TY_INT) { | |
780 | - o4(0xE8BD0002); // ldmfd sp!,{r1} | |
772 | + TypeTag tagR0 = pR0Type->tag; | |
773 | + TypeTag tagTOS = pTOSType->tag; | |
774 | + bool isFloatR0 = isFloatTag(tagR0); | |
775 | + bool isFloatTOS = isFloatTag(tagTOS); | |
776 | + if (!isFloatR0 && !isFloatTOS) { | |
777 | + bool isPtrR0 = tagR0 == TY_POINTER; | |
778 | + bool isPtrTOS = tagTOS == TY_POINTER; | |
779 | + if (isPtrR0 || isPtrTOS) { | |
780 | + if (isPtrR0 && isPtrTOS) { | |
781 | + if (op != OP_MINUS) { | |
782 | + error("Unsupported pointer-pointer operation %d.", op); | |
783 | + } | |
784 | + if (! typeEqual(pR0Type, pTOSType)) { | |
785 | + error("Incompatible pointer types for subtraction."); | |
786 | + } | |
787 | + o4(0xE8BD0002); // ldmfd sp!,{r1} | |
788 | + o4(0xE0410000); // sub r0,r1,r0 | |
789 | + popType(); | |
790 | + setR0Type(mkpInt); | |
791 | + int size = sizeOf(pR0Type->pHead); | |
792 | + if (size != 1) { | |
793 | + pushR0(); | |
794 | + li(size, mkpInt); | |
795 | + // TODO: Optimize for power-of-two. | |
796 | + genOp(OP_DIV); | |
797 | + } | |
798 | + } else { | |
799 | + if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) { | |
800 | + error("Unsupported pointer-scalar operation %d", op); | |
801 | + } | |
802 | + Type* pPtrType = isPtrR0 ? pR0Type : pTOSType; | |
803 | + o4(0xE8BD0002); // ldmfd sp!,{r1} | |
804 | + int size = sizeOf(pPtrType->pHead); | |
805 | + if (size != 1) { | |
806 | + // TODO: Optimize for power-of-two. | |
807 | + liReg(size, 2); | |
808 | + if (isPtrR0) { | |
809 | + o4(0x0E0010192); // mul r1,r2,r1 | |
810 | + } else { | |
811 | + o4(0x0E0000092); // mul r0,r2,r0 | |
812 | + } | |
813 | + } | |
814 | + switch(op) { | |
815 | + case OP_PLUS: | |
816 | + o4(0xE0810000); // add r0,r1,r0 | |
817 | + break; | |
818 | + case OP_MINUS: | |
819 | + o4(0xE0410000); // sub r0,r1,r0 | |
820 | + break; | |
821 | + } | |
822 | + popType(); | |
823 | + setR0Type(pPtrType); | |
824 | + } | |
825 | + } else { | |
826 | + o4(0xE8BD0002); // ldmfd sp!,{r1} | |
781 | 827 | mStackUse -= 4; |
782 | - switch(op) { | |
783 | - case OP_MUL: | |
784 | - o4(0x0E0000091); // mul r0,r1,r0 | |
785 | - break; | |
786 | - case OP_DIV: | |
787 | - callRuntime((void*) runtime_DIV); | |
788 | - break; | |
789 | - case OP_MOD: | |
790 | - callRuntime((void*) runtime_MOD); | |
791 | - break; | |
792 | - case OP_PLUS: | |
793 | - o4(0xE0810000); // add r0,r1,r0 | |
794 | - break; | |
795 | - case OP_MINUS: | |
796 | - o4(0xE0410000); // sub r0,r1,r0 | |
797 | - break; | |
798 | - case OP_SHIFT_LEFT: | |
799 | - o4(0xE1A00011); // lsl r0,r1,r0 | |
800 | - break; | |
801 | - case OP_SHIFT_RIGHT: | |
802 | - o4(0xE1A00051); // asr r0,r1,r0 | |
803 | - break; | |
804 | - case OP_BIT_AND: | |
805 | - o4(0xE0010000); // and r0,r1,r0 | |
806 | - break; | |
807 | - case OP_BIT_XOR: | |
808 | - o4(0xE0210000); // eor r0,r1,r0 | |
809 | - break; | |
810 | - case OP_BIT_OR: | |
811 | - o4(0xE1810000); // orr r0,r1,r0 | |
812 | - break; | |
813 | - case OP_BIT_NOT: | |
814 | - o4(0xE1E00000); // mvn r0, r0 | |
815 | - break; | |
816 | - default: | |
817 | - error("Unimplemented op %d\n", op); | |
818 | - break; | |
828 | + switch(op) { | |
829 | + case OP_MUL: | |
830 | + o4(0x0E0000091); // mul r0,r1,r0 | |
831 | + break; | |
832 | + case OP_DIV: | |
833 | + callRuntime((void*) runtime_DIV); | |
834 | + break; | |
835 | + case OP_MOD: | |
836 | + callRuntime((void*) runtime_MOD); | |
837 | + break; | |
838 | + case OP_PLUS: | |
839 | + o4(0xE0810000); // add r0,r1,r0 | |
840 | + break; | |
841 | + case OP_MINUS: | |
842 | + o4(0xE0410000); // sub r0,r1,r0 | |
843 | + break; | |
844 | + case OP_SHIFT_LEFT: | |
845 | + o4(0xE1A00011); // lsl r0,r1,r0 | |
846 | + break; | |
847 | + case OP_SHIFT_RIGHT: | |
848 | + o4(0xE1A00051); // asr r0,r1,r0 | |
849 | + break; | |
850 | + case OP_BIT_AND: | |
851 | + o4(0xE0010000); // and r0,r1,r0 | |
852 | + break; | |
853 | + case OP_BIT_XOR: | |
854 | + o4(0xE0210000); // eor r0,r1,r0 | |
855 | + break; | |
856 | + case OP_BIT_OR: | |
857 | + o4(0xE1810000); // orr r0,r1,r0 | |
858 | + break; | |
859 | + case OP_BIT_NOT: | |
860 | + o4(0xE1E00000); // mvn r0, r0 | |
861 | + break; | |
862 | + default: | |
863 | + error("Unimplemented op %d\n", op); | |
864 | + break; | |
865 | + } | |
866 | + popType(); | |
819 | 867 | } |
820 | - popType(); | |
821 | 868 | } else { |
822 | 869 | Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType; |
823 | 870 | if (pResultType->tag == TY_DOUBLE) { |
@@ -873,9 +920,9 @@ class Compiler : public ErrorSink { | ||
873 | 920 | switch(tag) { |
874 | 921 | case TY_INT: |
875 | 922 | o4(0xE3A01000); // mov r1, #0 |
876 | - o4(0xE1510000); // cmp r1, r1 | |
877 | - o4(0x03A00000); // moveq r0,#0 | |
878 | - o4(0x13A00001); // movne r0,#1 | |
923 | + o4(0xE1510000); // cmp r1, r0 | |
924 | + o4(0x03A00001); // moveq r0,#1 | |
925 | + o4(0x13A00000); // movne r0,#0 | |
879 | 926 | break; |
880 | 927 | case TY_FLOAT: |
881 | 928 | callRuntime((void*) runtime_is_zero_f); |
@@ -1589,6 +1636,22 @@ class Compiler : public ErrorSink { | ||
1589 | 1636 | popType(); |
1590 | 1637 | } |
1591 | 1638 | |
1639 | + void liReg(int t, int reg) { | |
1640 | + assert(reg >= 0 && reg < 16); | |
1641 | + int rN = (reg & 0xf) << 12; | |
1642 | + if (t >= 0 && t < 255) { | |
1643 | + o4((0xE3A00000 + t) | rN); // mov rN, #0 | |
1644 | + } else if (t >= -256 && t < 0) { | |
1645 | + // mvn means move constant ^ ~0 | |
1646 | + o4((0xE3E00001 - t) | rN); // mvn rN, #0 | |
1647 | + } else { | |
1648 | + o4(0xE51F0000 | rN); // ldr rN, .L3 | |
1649 | + o4(0xEA000000); // b .L99 | |
1650 | + o4(t); // .L3: .word 0 | |
1651 | + // .L99: | |
1652 | + } | |
1653 | + } | |
1654 | + | |
1592 | 1655 | void callRuntime(void* fn) { |
1593 | 1656 | o4(0xE59FC000); // ldr r12, .L1 |
1594 | 1657 | o4(0xEA000000); // b .L99 |
@@ -1897,12 +1960,53 @@ class Compiler : public ErrorSink { | ||
1897 | 1960 | bool isFloatR0 = isFloatTag(tagR0); |
1898 | 1961 | bool isFloatTOS = isFloatTag(tagTOS); |
1899 | 1962 | if (!isFloatR0 && !isFloatTOS) { |
1900 | - // TODO: Deal with pointer arithmetic | |
1901 | - o(0x59); /* pop %ecx */ | |
1902 | - o(decodeOp(op)); | |
1903 | - if (op == OP_MOD) | |
1904 | - o(0x92); /* xchg %edx, %eax */ | |
1905 | - popType(); | |
1963 | + bool isPtrR0 = tagR0 == TY_POINTER; | |
1964 | + bool isPtrTOS = tagTOS == TY_POINTER; | |
1965 | + if (isPtrR0 || isPtrTOS) { | |
1966 | + if (isPtrR0 && isPtrTOS) { | |
1967 | + if (op != OP_MINUS) { | |
1968 | + error("Unsupported pointer-pointer operation %d.", op); | |
1969 | + } | |
1970 | + if (! typeEqual(pR0Type, pTOSType)) { | |
1971 | + error("Incompatible pointer types for subtraction."); | |
1972 | + } | |
1973 | + o(0x59); /* pop %ecx */ | |
1974 | + o(decodeOp(op)); | |
1975 | + popType(); | |
1976 | + setR0Type(mkpInt); | |
1977 | + int size = sizeOf(pR0Type->pHead); | |
1978 | + if (size != 1) { | |
1979 | + pushR0(); | |
1980 | + li(size, mkpInt); | |
1981 | + // TODO: Optimize for power-of-two. | |
1982 | + genOp(OP_DIV); | |
1983 | + } | |
1984 | + } else { | |
1985 | + if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) { | |
1986 | + error("Unsupported pointer-scalar operation %d", op); | |
1987 | + } | |
1988 | + Type* pPtrType = isPtrR0 ? pR0Type : pTOSType; | |
1989 | + o(0x59); /* pop %ecx */ | |
1990 | + int size = sizeOf(pPtrType->pHead); | |
1991 | + if (size != 1) { | |
1992 | + // TODO: Optimize for power-of-two. | |
1993 | + if (isPtrR0) { | |
1994 | + oad(0xC969, size); // imull $size, %ecx | |
1995 | + } else { | |
1996 | + oad(0xC069, size); // mul $size, %eax | |
1997 | + } | |
1998 | + } | |
1999 | + o(decodeOp(op)); | |
2000 | + popType(); | |
2001 | + setR0Type(pPtrType); | |
2002 | + } | |
2003 | + } else { | |
2004 | + o(0x59); /* pop %ecx */ | |
2005 | + o(decodeOp(op)); | |
2006 | + if (op == OP_MOD) | |
2007 | + o(0x92); /* xchg %edx, %eax */ | |
2008 | + popType(); | |
2009 | + } | |
1906 | 2010 | } else { |
1907 | 2011 | Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType; |
1908 | 2012 | setupFloatOperands(); |
@@ -2347,7 +2451,6 @@ class Compiler : public ErrorSink { | ||
2347 | 2451 | return result; |
2348 | 2452 | } |
2349 | 2453 | |
2350 | - | |
2351 | 2454 | static const int operatorHelper[]; |
2352 | 2455 | |
2353 | 2456 | int decodeOp(int op) { |
@@ -4003,7 +4106,7 @@ class Compiler : public ErrorSink { | ||
4003 | 4106 | } |
4004 | 4107 | } |
4005 | 4108 | |
4006 | - bool typeEqual(Type* a, Type* b) { | |
4109 | + static bool typeEqual(Type* a, Type* b) { | |
4007 | 4110 | if (a == b) { |
4008 | 4111 | return true; |
4009 | 4112 | } |
@@ -4550,6 +4653,7 @@ class Compiler : public ErrorSink { | ||
4550 | 4653 | error("No code generator defined."); |
4551 | 4654 | } else { |
4552 | 4655 | pGen->setErrorSink(this); |
4656 | + pGen->setTypes(mkpInt); | |
4553 | 4657 | } |
4554 | 4658 | } |
4555 | 4659 |
@@ -4572,6 +4676,7 @@ public: | ||
4572 | 4676 | int compile(const char* text, size_t textLength) { |
4573 | 4677 | int result; |
4574 | 4678 | |
4679 | + createPrimitiveTypes(); | |
4575 | 4680 | cleanup(); |
4576 | 4681 | clear(); |
4577 | 4682 | mTokenTable.setArena(&mGlobalArena); |
@@ -4581,7 +4686,6 @@ public: | ||
4581 | 4686 | mLocals.setTokenTable(&mTokenTable); |
4582 | 4687 | |
4583 | 4688 | internKeywords(); |
4584 | - createPrimitiveTypes(); | |
4585 | 4689 | codeBuf.init(ALLOC_SIZE); |
4586 | 4690 | setArchitecture(NULL); |
4587 | 4691 | if (!pGen) { |
@@ -0,0 +1,15 @@ | ||
1 | +int main() { | |
2 | + int* pa = (int*) malloc(100); | |
3 | + int* pb = pa + 1; | |
4 | + int* pc = (int*) 0; | |
5 | + *pa = 1; | |
6 | + *pb = 2; | |
7 | + printf("Pointer difference: %d %d\n", pb - pa, ((int) pb) - ((int) pa)); | |
8 | + int c = * (pa + 1); | |
9 | + printf("Pointer addition: %d\n", c); | |
10 | + printf("Pointer comparison to zero: %d %d %d\n", pa == 0, pb == 0, pc == 0); | |
11 | + printf("Pointer comparison: %d %d %d %d %d\n", pa < pb, pa == pb, pa > pb, ! pb, ! pc); | |
12 | + free(pa); | |
13 | + return 0; | |
14 | +} | |
15 | + |
@@ -255,6 +255,14 @@ Testing read/write (double*): 8.8 9.9 | ||
255 | 255 | result: 0""", """a = 99, b = 41 |
256 | 256 | ga = 100, gb = 44""") |
257 | 257 | |
258 | + def testPointerArithmetic(self): | |
259 | + self.compileCheck(["-R", "data/pointers.c"], """Executing compiled code: | |
260 | +result: 0""", """Pointer difference: 1 4 | |
261 | +Pointer addition: 2 | |
262 | +Pointer comparison to zero: 0 0 1 | |
263 | +Pointer comparison: 1 0 0 0 1 | |
264 | +""") | |
265 | + | |
258 | 266 | |
259 | 267 | if __name__ == '__main__': |
260 | 268 | if not outputCanRun(): |