• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

system/corennnnn


Commit MetaInfo

Revisiona8f427f60620d766b201c9a84c457fa5dbaf95d4 (tree)
Time2009-07-14 10:40:08
AuthorJack Palevich <jackpal@goog...>
CommiterJack Palevich

Log Message

Implement pointer arithmetic.

Change Summary

Incremental Difference

--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -269,6 +269,10 @@ class Compiler : public ErrorSink {
269269 }
270270 }
271271
272+ void setTypes(Type* pInt) {
273+ mkpInt = pInt;
274+ }
275+
272276 /* Emit a function prolog.
273277 * pDecl is the function declaration, which gives the arguments.
274278 * Save the old value of the FP.
@@ -545,6 +549,8 @@ class Compiler : public ErrorSink {
545549 return tag == TY_FLOAT || tag == TY_DOUBLE;
546550 }
547551
552+ Type* mkpInt;
553+
548554 private:
549555 Vector<Type*> mExpressionStack;
550556 CodeBuf* pCodeBuf;
@@ -615,18 +621,7 @@ class Compiler : public ErrorSink {
615621
616622 /* load immediate value */
617623 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);
630625 setR0Type(pType);
631626 }
632627
@@ -774,50 +769,102 @@ class Compiler : public ErrorSink {
774769 LOG_API("genOp(%d);\n", op);
775770 Type* pR0Type = getR0Type();
776771 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}
781827 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();
819867 }
820- popType();
821868 } else {
822869 Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType;
823870 if (pResultType->tag == TY_DOUBLE) {
@@ -873,9 +920,9 @@ class Compiler : public ErrorSink {
873920 switch(tag) {
874921 case TY_INT:
875922 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
879926 break;
880927 case TY_FLOAT:
881928 callRuntime((void*) runtime_is_zero_f);
@@ -1589,6 +1636,22 @@ class Compiler : public ErrorSink {
15891636 popType();
15901637 }
15911638
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+
15921655 void callRuntime(void* fn) {
15931656 o4(0xE59FC000); // ldr r12, .L1
15941657 o4(0xEA000000); // b .L99
@@ -1897,12 +1960,53 @@ class Compiler : public ErrorSink {
18971960 bool isFloatR0 = isFloatTag(tagR0);
18981961 bool isFloatTOS = isFloatTag(tagTOS);
18991962 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+ }
19062010 } else {
19072011 Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType;
19082012 setupFloatOperands();
@@ -2347,7 +2451,6 @@ class Compiler : public ErrorSink {
23472451 return result;
23482452 }
23492453
2350-
23512454 static const int operatorHelper[];
23522455
23532456 int decodeOp(int op) {
@@ -4003,7 +4106,7 @@ class Compiler : public ErrorSink {
40034106 }
40044107 }
40054108
4006- bool typeEqual(Type* a, Type* b) {
4109+ static bool typeEqual(Type* a, Type* b) {
40074110 if (a == b) {
40084111 return true;
40094112 }
@@ -4550,6 +4653,7 @@ class Compiler : public ErrorSink {
45504653 error("No code generator defined.");
45514654 } else {
45524655 pGen->setErrorSink(this);
4656+ pGen->setTypes(mkpInt);
45534657 }
45544658 }
45554659
@@ -4572,6 +4676,7 @@ public:
45724676 int compile(const char* text, size_t textLength) {
45734677 int result;
45744678
4679+ createPrimitiveTypes();
45754680 cleanup();
45764681 clear();
45774682 mTokenTable.setArena(&mGlobalArena);
@@ -4581,7 +4686,6 @@ public:
45814686 mLocals.setTokenTable(&mTokenTable);
45824687
45834688 internKeywords();
4584- createPrimitiveTypes();
45854689 codeBuf.init(ALLOC_SIZE);
45864690 setArchitecture(NULL);
45874691 if (!pGen) {
--- /dev/null
+++ b/libacc/tests/data/pointers.c
@@ -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+
--- a/libacc/tests/test.py
+++ b/libacc/tests/test.py
@@ -255,6 +255,14 @@ Testing read/write (double*): 8.8 9.9
255255 result: 0""", """a = 99, b = 41
256256 ga = 100, gb = 44""")
257257
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+
258266
259267 if __name__ == '__main__':
260268 if not outputCanRun():