Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e525099 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 7050

* changes:
  Implement pointer arithmetic.
parents dc610605 a8f427f6
Loading
Loading
Loading
Loading
+170 −66
Original line number Diff line number Diff line
@@ -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.
@@ -545,6 +549,8 @@ class Compiler : public ErrorSink {
            return tag == TY_FLOAT || tag == TY_DOUBLE;
        }

        Type* mkpInt;

    private:
        Vector<Type*> mExpressionStack;
        CodeBuf* pCodeBuf;
@@ -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);
        }

@@ -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) {
@@ -818,6 +864,7 @@ class Compiler : public ErrorSink {
                        break;
                    }
                    popType();
                }
            } else {
                Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType;
                if (pResultType->tag == TY_DOUBLE) {
@@ -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);
@@ -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
@@ -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();
@@ -2347,7 +2451,6 @@ class Compiler : public ErrorSink {
            return result;
        }


        static const int operatorHelper[];

        int decodeOp(int op) {
@@ -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;
        }
@@ -4550,6 +4653,7 @@ class Compiler : public ErrorSink {
            error("No code generator defined.");
        } else {
            pGen->setErrorSink(this);
            pGen->setTypes(mkpInt);
        }
    }

@@ -4572,6 +4676,7 @@ public:
    int compile(const char* text, size_t textLength) {
        int result;

        createPrimitiveTypes();
        cleanup();
        clear();
        mTokenTable.setArena(&mGlobalArena);
@@ -4581,7 +4686,6 @@ public:
        mLocals.setTokenTable(&mTokenTable);

        internKeywords();
        createPrimitiveTypes();
        codeBuf.init(ALLOC_SIZE);
        setArchitecture(NULL);
        if (!pGen) {
+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;
}
+8 −0
Original line number Diff line number Diff line
@@ -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():