Loading libacc/acc.cpp +170 −66 Original line number Diff line number Diff line Loading @@ -269,6 +269,10 @@ class Compiler : public ErrorSink { } } void setTypes(Type* pInt) { mkpInt = pInt; } /* Emit a function prolog. * pDecl is the function declaration, which gives the arguments. * Save the old value of the FP. Loading Loading @@ -545,6 +549,8 @@ class Compiler : public ErrorSink { return tag == TY_FLOAT || tag == TY_DOUBLE; } Type* mkpInt; private: Vector<Type*> mExpressionStack; CodeBuf* pCodeBuf; Loading Loading @@ -615,18 +621,7 @@ class Compiler : public ErrorSink { /* load immediate value */ virtual void li(int t, Type* pType) { LOG_API("li(%d);\n", t); if (t >= 0 && t < 255) { o4(0xE3A00000 + t); // mov r0, #0 } else if (t >= -256 && t < 0) { // mvn means move constant ^ ~0 o4(0xE3E00001 - t); // mvn r0, #0 } else { o4(0xE51F0000); // ldr r0, .L3 o4(0xEA000000); // b .L99 o4(t); // .L3: .word 0 // .L99: } liReg(t, 0); setR0Type(pType); } Loading Loading @@ -774,9 +769,60 @@ class Compiler : public ErrorSink { LOG_API("genOp(%d);\n", op); Type* pR0Type = getR0Type(); Type* pTOSType = getTOSType(); TypeTag tagR0 = collapseType(pR0Type->tag); TypeTag tagTOS = collapseType(pTOSType->tag); if (tagR0 == TY_INT && tagTOS == TY_INT) { TypeTag tagR0 = pR0Type->tag; TypeTag tagTOS = pTOSType->tag; bool isFloatR0 = isFloatTag(tagR0); bool isFloatTOS = isFloatTag(tagTOS); if (!isFloatR0 && !isFloatTOS) { bool isPtrR0 = tagR0 == TY_POINTER; bool isPtrTOS = tagTOS == TY_POINTER; if (isPtrR0 || isPtrTOS) { if (isPtrR0 && isPtrTOS) { if (op != OP_MINUS) { error("Unsupported pointer-pointer operation %d.", op); } if (! typeEqual(pR0Type, pTOSType)) { error("Incompatible pointer types for subtraction."); } o4(0xE8BD0002); // ldmfd sp!,{r1} o4(0xE0410000); // sub r0,r1,r0 popType(); setR0Type(mkpInt); int size = sizeOf(pR0Type->pHead); if (size != 1) { pushR0(); li(size, mkpInt); // TODO: Optimize for power-of-two. genOp(OP_DIV); } } else { if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) { error("Unsupported pointer-scalar operation %d", op); } Type* pPtrType = isPtrR0 ? pR0Type : pTOSType; o4(0xE8BD0002); // ldmfd sp!,{r1} int size = sizeOf(pPtrType->pHead); if (size != 1) { // TODO: Optimize for power-of-two. liReg(size, 2); if (isPtrR0) { o4(0x0E0010192); // mul r1,r2,r1 } else { o4(0x0E0000092); // mul r0,r2,r0 } } switch(op) { case OP_PLUS: o4(0xE0810000); // add r0,r1,r0 break; case OP_MINUS: o4(0xE0410000); // sub r0,r1,r0 break; } popType(); setR0Type(pPtrType); } } else { o4(0xE8BD0002); // ldmfd sp!,{r1} mStackUse -= 4; switch(op) { Loading Loading @@ -818,6 +864,7 @@ class Compiler : public ErrorSink { break; } popType(); } } else { Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType; if (pResultType->tag == TY_DOUBLE) { Loading Loading @@ -873,9 +920,9 @@ class Compiler : public ErrorSink { switch(tag) { case TY_INT: o4(0xE3A01000); // mov r1, #0 o4(0xE1510000); // cmp r1, r1 o4(0x03A00000); // moveq r0,#0 o4(0x13A00001); // movne r0,#1 o4(0xE1510000); // cmp r1, r0 o4(0x03A00001); // moveq r0,#1 o4(0x13A00000); // movne r0,#0 break; case TY_FLOAT: callRuntime((void*) runtime_is_zero_f); Loading Loading @@ -1589,6 +1636,22 @@ class Compiler : public ErrorSink { popType(); } void liReg(int t, int reg) { assert(reg >= 0 && reg < 16); int rN = (reg & 0xf) << 12; if (t >= 0 && t < 255) { o4((0xE3A00000 + t) | rN); // mov rN, #0 } else if (t >= -256 && t < 0) { // mvn means move constant ^ ~0 o4((0xE3E00001 - t) | rN); // mvn rN, #0 } else { o4(0xE51F0000 | rN); // ldr rN, .L3 o4(0xEA000000); // b .L99 o4(t); // .L3: .word 0 // .L99: } } void callRuntime(void* fn) { o4(0xE59FC000); // ldr r12, .L1 o4(0xEA000000); // b .L99 Loading Loading @@ -1897,12 +1960,53 @@ class Compiler : public ErrorSink { bool isFloatR0 = isFloatTag(tagR0); bool isFloatTOS = isFloatTag(tagTOS); if (!isFloatR0 && !isFloatTOS) { // TODO: Deal with pointer arithmetic bool isPtrR0 = tagR0 == TY_POINTER; bool isPtrTOS = tagTOS == TY_POINTER; if (isPtrR0 || isPtrTOS) { if (isPtrR0 && isPtrTOS) { if (op != OP_MINUS) { error("Unsupported pointer-pointer operation %d.", op); } if (! typeEqual(pR0Type, pTOSType)) { error("Incompatible pointer types for subtraction."); } o(0x59); /* pop %ecx */ o(decodeOp(op)); popType(); setR0Type(mkpInt); int size = sizeOf(pR0Type->pHead); if (size != 1) { pushR0(); li(size, mkpInt); // TODO: Optimize for power-of-two. genOp(OP_DIV); } } else { if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) { error("Unsupported pointer-scalar operation %d", op); } Type* pPtrType = isPtrR0 ? pR0Type : pTOSType; o(0x59); /* pop %ecx */ int size = sizeOf(pPtrType->pHead); if (size != 1) { // TODO: Optimize for power-of-two. if (isPtrR0) { oad(0xC969, size); // imull $size, %ecx } else { oad(0xC069, size); // mul $size, %eax } } o(decodeOp(op)); popType(); setR0Type(pPtrType); } } else { o(0x59); /* pop %ecx */ o(decodeOp(op)); if (op == OP_MOD) o(0x92); /* xchg %edx, %eax */ popType(); } } else { Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType; setupFloatOperands(); Loading Loading @@ -2347,7 +2451,6 @@ class Compiler : public ErrorSink { return result; } static const int operatorHelper[]; int decodeOp(int op) { Loading Loading @@ -4003,7 +4106,7 @@ class Compiler : public ErrorSink { } } bool typeEqual(Type* a, Type* b) { static bool typeEqual(Type* a, Type* b) { if (a == b) { return true; } Loading Loading @@ -4550,6 +4653,7 @@ class Compiler : public ErrorSink { error("No code generator defined."); } else { pGen->setErrorSink(this); pGen->setTypes(mkpInt); } } Loading @@ -4572,6 +4676,7 @@ public: int compile(const char* text, size_t textLength) { int result; createPrimitiveTypes(); cleanup(); clear(); mTokenTable.setArena(&mGlobalArena); Loading @@ -4581,7 +4686,6 @@ public: mLocals.setTokenTable(&mTokenTable); internKeywords(); createPrimitiveTypes(); codeBuf.init(ALLOC_SIZE); setArchitecture(NULL); if (!pGen) { Loading libacc/tests/data/pointers.c 0 → 100644 +15 −0 Original line number Diff line number Diff line int main() { int* pa = (int*) malloc(100); int* pb = pa + 1; int* pc = (int*) 0; *pa = 1; *pb = 2; printf("Pointer difference: %d %d\n", pb - pa, ((int) pb) - ((int) pa)); int c = * (pa + 1); printf("Pointer addition: %d\n", c); printf("Pointer comparison to zero: %d %d %d\n", pa == 0, pb == 0, pc == 0); printf("Pointer comparison: %d %d %d %d %d\n", pa < pb, pa == pb, pa > pb, ! pb, ! pc); free(pa); return 0; } libacc/tests/test.py +8 −0 Original line number Diff line number Diff line Loading @@ -255,6 +255,14 @@ Testing read/write (double*): 8.8 9.9 result: 0""", """a = 99, b = 41 ga = 100, gb = 44""") def testPointerArithmetic(self): self.compileCheck(["-R", "data/pointers.c"], """Executing compiled code: result: 0""", """Pointer difference: 1 4 Pointer addition: 2 Pointer comparison to zero: 0 0 1 Pointer comparison: 1 0 0 0 1 """) if __name__ == '__main__': if not outputCanRun(): Loading Loading
libacc/acc.cpp +170 −66 Original line number Diff line number Diff line Loading @@ -269,6 +269,10 @@ class Compiler : public ErrorSink { } } void setTypes(Type* pInt) { mkpInt = pInt; } /* Emit a function prolog. * pDecl is the function declaration, which gives the arguments. * Save the old value of the FP. Loading Loading @@ -545,6 +549,8 @@ class Compiler : public ErrorSink { return tag == TY_FLOAT || tag == TY_DOUBLE; } Type* mkpInt; private: Vector<Type*> mExpressionStack; CodeBuf* pCodeBuf; Loading Loading @@ -615,18 +621,7 @@ class Compiler : public ErrorSink { /* load immediate value */ virtual void li(int t, Type* pType) { LOG_API("li(%d);\n", t); if (t >= 0 && t < 255) { o4(0xE3A00000 + t); // mov r0, #0 } else if (t >= -256 && t < 0) { // mvn means move constant ^ ~0 o4(0xE3E00001 - t); // mvn r0, #0 } else { o4(0xE51F0000); // ldr r0, .L3 o4(0xEA000000); // b .L99 o4(t); // .L3: .word 0 // .L99: } liReg(t, 0); setR0Type(pType); } Loading Loading @@ -774,9 +769,60 @@ class Compiler : public ErrorSink { LOG_API("genOp(%d);\n", op); Type* pR0Type = getR0Type(); Type* pTOSType = getTOSType(); TypeTag tagR0 = collapseType(pR0Type->tag); TypeTag tagTOS = collapseType(pTOSType->tag); if (tagR0 == TY_INT && tagTOS == TY_INT) { TypeTag tagR0 = pR0Type->tag; TypeTag tagTOS = pTOSType->tag; bool isFloatR0 = isFloatTag(tagR0); bool isFloatTOS = isFloatTag(tagTOS); if (!isFloatR0 && !isFloatTOS) { bool isPtrR0 = tagR0 == TY_POINTER; bool isPtrTOS = tagTOS == TY_POINTER; if (isPtrR0 || isPtrTOS) { if (isPtrR0 && isPtrTOS) { if (op != OP_MINUS) { error("Unsupported pointer-pointer operation %d.", op); } if (! typeEqual(pR0Type, pTOSType)) { error("Incompatible pointer types for subtraction."); } o4(0xE8BD0002); // ldmfd sp!,{r1} o4(0xE0410000); // sub r0,r1,r0 popType(); setR0Type(mkpInt); int size = sizeOf(pR0Type->pHead); if (size != 1) { pushR0(); li(size, mkpInt); // TODO: Optimize for power-of-two. genOp(OP_DIV); } } else { if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) { error("Unsupported pointer-scalar operation %d", op); } Type* pPtrType = isPtrR0 ? pR0Type : pTOSType; o4(0xE8BD0002); // ldmfd sp!,{r1} int size = sizeOf(pPtrType->pHead); if (size != 1) { // TODO: Optimize for power-of-two. liReg(size, 2); if (isPtrR0) { o4(0x0E0010192); // mul r1,r2,r1 } else { o4(0x0E0000092); // mul r0,r2,r0 } } switch(op) { case OP_PLUS: o4(0xE0810000); // add r0,r1,r0 break; case OP_MINUS: o4(0xE0410000); // sub r0,r1,r0 break; } popType(); setR0Type(pPtrType); } } else { o4(0xE8BD0002); // ldmfd sp!,{r1} mStackUse -= 4; switch(op) { Loading Loading @@ -818,6 +864,7 @@ class Compiler : public ErrorSink { break; } popType(); } } else { Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType; if (pResultType->tag == TY_DOUBLE) { Loading Loading @@ -873,9 +920,9 @@ class Compiler : public ErrorSink { switch(tag) { case TY_INT: o4(0xE3A01000); // mov r1, #0 o4(0xE1510000); // cmp r1, r1 o4(0x03A00000); // moveq r0,#0 o4(0x13A00001); // movne r0,#1 o4(0xE1510000); // cmp r1, r0 o4(0x03A00001); // moveq r0,#1 o4(0x13A00000); // movne r0,#0 break; case TY_FLOAT: callRuntime((void*) runtime_is_zero_f); Loading Loading @@ -1589,6 +1636,22 @@ class Compiler : public ErrorSink { popType(); } void liReg(int t, int reg) { assert(reg >= 0 && reg < 16); int rN = (reg & 0xf) << 12; if (t >= 0 && t < 255) { o4((0xE3A00000 + t) | rN); // mov rN, #0 } else if (t >= -256 && t < 0) { // mvn means move constant ^ ~0 o4((0xE3E00001 - t) | rN); // mvn rN, #0 } else { o4(0xE51F0000 | rN); // ldr rN, .L3 o4(0xEA000000); // b .L99 o4(t); // .L3: .word 0 // .L99: } } void callRuntime(void* fn) { o4(0xE59FC000); // ldr r12, .L1 o4(0xEA000000); // b .L99 Loading Loading @@ -1897,12 +1960,53 @@ class Compiler : public ErrorSink { bool isFloatR0 = isFloatTag(tagR0); bool isFloatTOS = isFloatTag(tagTOS); if (!isFloatR0 && !isFloatTOS) { // TODO: Deal with pointer arithmetic bool isPtrR0 = tagR0 == TY_POINTER; bool isPtrTOS = tagTOS == TY_POINTER; if (isPtrR0 || isPtrTOS) { if (isPtrR0 && isPtrTOS) { if (op != OP_MINUS) { error("Unsupported pointer-pointer operation %d.", op); } if (! typeEqual(pR0Type, pTOSType)) { error("Incompatible pointer types for subtraction."); } o(0x59); /* pop %ecx */ o(decodeOp(op)); popType(); setR0Type(mkpInt); int size = sizeOf(pR0Type->pHead); if (size != 1) { pushR0(); li(size, mkpInt); // TODO: Optimize for power-of-two. genOp(OP_DIV); } } else { if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) { error("Unsupported pointer-scalar operation %d", op); } Type* pPtrType = isPtrR0 ? pR0Type : pTOSType; o(0x59); /* pop %ecx */ int size = sizeOf(pPtrType->pHead); if (size != 1) { // TODO: Optimize for power-of-two. if (isPtrR0) { oad(0xC969, size); // imull $size, %ecx } else { oad(0xC069, size); // mul $size, %eax } } o(decodeOp(op)); popType(); setR0Type(pPtrType); } } else { o(0x59); /* pop %ecx */ o(decodeOp(op)); if (op == OP_MOD) o(0x92); /* xchg %edx, %eax */ popType(); } } else { Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType; setupFloatOperands(); Loading Loading @@ -2347,7 +2451,6 @@ class Compiler : public ErrorSink { return result; } static const int operatorHelper[]; int decodeOp(int op) { Loading Loading @@ -4003,7 +4106,7 @@ class Compiler : public ErrorSink { } } bool typeEqual(Type* a, Type* b) { static bool typeEqual(Type* a, Type* b) { if (a == b) { return true; } Loading Loading @@ -4550,6 +4653,7 @@ class Compiler : public ErrorSink { error("No code generator defined."); } else { pGen->setErrorSink(this); pGen->setTypes(mkpInt); } } Loading @@ -4572,6 +4676,7 @@ public: int compile(const char* text, size_t textLength) { int result; createPrimitiveTypes(); cleanup(); clear(); mTokenTable.setArena(&mGlobalArena); Loading @@ -4581,7 +4686,6 @@ public: mLocals.setTokenTable(&mTokenTable); internKeywords(); createPrimitiveTypes(); codeBuf.init(ALLOC_SIZE); setArchitecture(NULL); if (!pGen) { Loading
libacc/tests/data/pointers.c 0 → 100644 +15 −0 Original line number Diff line number Diff line int main() { int* pa = (int*) malloc(100); int* pb = pa + 1; int* pc = (int*) 0; *pa = 1; *pb = 2; printf("Pointer difference: %d %d\n", pb - pa, ((int) pb) - ((int) pa)); int c = * (pa + 1); printf("Pointer addition: %d\n", c); printf("Pointer comparison to zero: %d %d %d\n", pa == 0, pb == 0, pc == 0); printf("Pointer comparison: %d %d %d %d %d\n", pa < pb, pa == pb, pa > pb, ! pb, ! pc); free(pa); return 0; }
libacc/tests/test.py +8 −0 Original line number Diff line number Diff line Loading @@ -255,6 +255,14 @@ Testing read/write (double*): 8.8 9.9 result: 0""", """a = 99, b = 41 ga = 100, gb = 44""") def testPointerArithmetic(self): self.compileCheck(["-R", "data/pointers.c"], """Executing compiled code: result: 0""", """Pointer difference: 1 4 Pointer addition: 2 Pointer comparison to zero: 0 0 1 Pointer comparison: 1 0 0 0 1 """) if __name__ == '__main__': if not outputCanRun(): Loading