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

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

Merge change 7792

* changes:
  Code generator cleanup
parents 0761a49c 58c30eef
Loading
Loading
Loading
Loading
+153 −124
Original line number Diff line number Diff line
@@ -282,6 +282,11 @@ class Compiler : public ErrorSink {
            }
        }

        /* Give the code generator some utility types so it can
         * use its own types as needed for the results of some
         * operations like gcmp.
         */

        void setTypes(Type* pInt) {
            mkpInt = pInt;
        }
@@ -312,7 +317,7 @@ class Compiler : public ErrorSink {
                                  int localVariableSize) = 0;

        /* load immediate value to R0 */
        virtual void li(int i, Type* pType) = 0;
        virtual void li(int i) = 0;

        /* Load floating point value from global address. */
        virtual void loadFloat(int address, Type* pType) = 0;
@@ -333,7 +338,7 @@ class Compiler : public ErrorSink {
         * Pops TOS.
         * op specifies the comparison.
         */
        virtual void gcmp(int op, Type* pResultType) = 0;
        virtual void gcmp(int op) = 0;

        /* Perform the arithmetic op specified by op. TOS is the
         * left argument, R0 is the right argument.
@@ -344,7 +349,7 @@ class Compiler : public ErrorSink {
        /* Compare 0 against R0, and store the boolean result in R0.
         * op specifies the comparison.
         */
        virtual void gUnaryCmp(int op, Type* pResultType) = 0;
        virtual void gUnaryCmp(int op) = 0;

        /* Perform the arithmetic op specified by op. 0 is the
         * left argument, R0 is the right argument.
@@ -355,16 +360,18 @@ class Compiler : public ErrorSink {
         */
        virtual void pushR0() = 0;

        /* Pop R0 from the stack.
         */
        virtual void popR0() = 0;

        /* Store R0 to the address stored in TOS.
         * The TOS is popped.
         * pPointerType is the type of the pointer (of the input R0).
         */
        virtual void storeR0ToTOS(Type* pPointerType) = 0;
        virtual void storeR0ToTOS() = 0;

        /* Load R0 from the address stored in R0.
         * pPointerType is the type of the pointer (of the input R0).
         */
        virtual void loadR0FromR0(Type* pPointerType) = 0;
        virtual void loadR0FromR0() = 0;

        /* Load the absolute address of a variable to R0.
         * If ea <= LOCAL, then this is a local variable, or an
@@ -384,11 +391,8 @@ class Compiler : public ErrorSink {
         * If ea <= LOCAL, then this is a local variable, or an
         * argument, addressed relative to FP.
         * else it is an absolute global address.
         * If isIncDec is true, then the stored variable's value
         * should be post-incremented or post-decremented, based
         * on the value of op.
         */
        virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) = 0;
        virtual void loadR0(int ea, Type* pType) = 0;

        /**
         * Convert R0 to the given type.
@@ -636,9 +640,9 @@ class Compiler : public ErrorSink {
        }

        /* load immediate value */
        virtual void li(int t, Type* pType) {
        virtual void li(int t) {
            liReg(t, 0);
            setR0Type(pType);
            setR0Type(mkpInt);
        }

        virtual void loadFloat(int address, Type* pType) {
@@ -685,14 +689,13 @@ class Compiler : public ErrorSink {
            return o4(branch | encodeAddress(t));
        }

        virtual void gcmp(int op, Type* pResultType) {
        virtual void gcmp(int op) {
            Type* pR0Type = getR0Type();
            Type* pTOSType = getTOSType();
            TypeTag tagR0 = collapseType(pR0Type->tag);
            TypeTag tagTOS = collapseType(pTOSType->tag);
            if (tagR0 == TY_INT && tagTOS == TY_INT) {
                o4(0xE8BD0002);  // ldmfd   sp!,{r1}
                mStackUse -= 4;
                setupIntPtrArgs();
                o4(0xE1510000); // cmp r1, r1
                switch(op) {
                case OP_EQUALS:
@@ -723,7 +726,6 @@ class Compiler : public ErrorSink {
                    error("Unknown comparison op %d", op);
                    break;
                }
                popType();
            } else if (tagR0 == TY_DOUBLE || tagTOS == TY_DOUBLE) {
                setupDoubleArgs();
                switch(op) {
@@ -775,7 +777,7 @@ class Compiler : public ErrorSink {
                        break;
                }
            }
            setR0Type(pResultType);
            setR0Type(mkpInt);
        }

        virtual void genOp(int op) {
@@ -786,6 +788,7 @@ class Compiler : public ErrorSink {
            bool isFloatR0 = isFloatTag(tagR0);
            bool isFloatTOS = isFloatTag(tagTOS);
            if (!isFloatR0 && !isFloatTOS) {
                setupIntPtrArgs();
                bool isPtrR0 = tagR0 == TY_POINTER;
                bool isPtrTOS = tagTOS == TY_POINTER;
                if (isPtrR0 || isPtrTOS) {
@@ -796,14 +799,12 @@ class Compiler : public ErrorSink {
                        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);
                            li(size);
                            // TODO: Optimize for power-of-two.
                            genOp(OP_DIV);
                        }
@@ -812,7 +813,6 @@ class Compiler : public ErrorSink {
                            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.
@@ -831,12 +831,9 @@ class Compiler : public ErrorSink {
                            o4(0xE0410000); // sub     r0,r1,r0
                            break;
                        }
                        popType();
                        setR0Type(pPtrType);
                    }
                } else {
                    o4(0xE8BD0002); // ldmfd   sp!,{r1}
                mStackUse -= 4;
                    switch(op) {
                        case OP_MUL:
                        o4(0x0E0000091); // mul     r0,r1,r0
@@ -875,7 +872,6 @@ class Compiler : public ErrorSink {
                        error("Unimplemented op %d\n", op);
                        break;
                    }
                    popType();
                }
            } else {
                Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType;
@@ -922,7 +918,7 @@ class Compiler : public ErrorSink {
            }
        }

        virtual void gUnaryCmp(int op, Type* pResultType) {
        virtual void gUnaryCmp(int op) {
            if (op != OP_LOGICAL_NOT) {
                error("Unknown unary cmp %d", op);
            } else {
@@ -946,7 +942,7 @@ class Compiler : public ErrorSink {
                        break;
                }
            }
            setR0Type(pResultType);
            setR0Type(mkpInt);
        }

        virtual void genUnaryOp(int op) {
@@ -1005,7 +1001,28 @@ class Compiler : public ErrorSink {
            LOG_STACK("pushR0: %d\n", mStackUse);
        }

        virtual void storeR0ToTOS(Type* pPointerType) {
        virtual void popR0() {
            Type* pTOSType = getTOSType();
            switch (collapseType(pTOSType->tag)){
                case TY_INT:
                case TY_FLOAT:
                    o4(0xE8BD0001);  // ldmfd   sp!,{r0}
                    mStackUse -= 4;
                    break;
                case TY_DOUBLE:
                    o4(0xE8BD0003);  // ldmfd   sp!,{r0, r1}  // Restore R0
                        mStackUse -= 8;
                    break;
                default:
                    error("Can't pop this type.");
                    break;
            }
            popType();
            LOG_STACK("popR0: %d\n", mStackUse);
        }

        virtual void storeR0ToTOS() {
            Type* pPointerType = getTOSType();
            assert(pPointerType->tag == TY_POINTER);
            o4(0xE8BD0004);  // ldmfd   sp!,{r2}
            popType();
@@ -1027,7 +1044,8 @@ class Compiler : public ErrorSink {
            }
        }

        virtual void loadR0FromR0(Type* pPointerType) {
        virtual void loadR0FromR0() {
            Type* pPointerType = getR0Type();
            assert(pPointerType->tag == TY_POINTER);
            switch (pPointerType->pHead->tag) {
                case TY_INT:
@@ -1149,7 +1167,7 @@ class Compiler : public ErrorSink {
            }
        }

        virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) {
        virtual void loadR0(int ea, Type* pType) {
            TypeTag tag = pType->tag;
            switch (tag) {
                case TY_CHAR:
@@ -1170,10 +1188,6 @@ class Compiler : public ErrorSink {
                        o4(ea);         // .L1:   .word ea
                        o4(0xE5D20000); // .L99:  ldrb r0, [r2]
                    }

                    if (isIncDec) {
                        error("inc/dec not implemented for char.");
                    }
                    break;
                case TY_POINTER:
                case TY_INT:
@@ -1195,37 +1209,6 @@ class Compiler : public ErrorSink {
                        o4(ea);         // .L1:   .word ea
                        o4(0xE5920000); // .L99:  ldr r0, [r2]
                    }

                    if (isIncDec) {
                        if (tag == TY_INT) {
                            switch (op) {
                            case OP_INCREMENT:
                                o4(0xE2801001); // add r1, r0, #1
                                break;
                            case OP_DECREMENT:
                                o4(0xE2401001); // sub r1, r0, #1
                                break;
                            default:
                                error("unknown opcode: %d", op);
                            }
                            if (ea < LOCAL) {
                                // Local, fp relative
                                // Don't need range check, was already checked above
                                if (ea < 0) {
                                    o4(0xE50B1000 | (0xfff & (-ea))); // str r1, [fp,#-ea]
                                } else {
                                    o4(0xE58B1000 | (0xfff & ea));    // str r1, [fp,#ea]
                                }
                            } else{
                                // Global, absolute
                                // r2 is already set up from before.
                                o4(0xE5821000); // str r1, [r2]
                           }
                        }
                        else {
                            error("inc/dec not implemented for float.");
                        }
                    }
                    break;
                case TY_DOUBLE:
                    if ((ea & 0x7) != 0) {
@@ -1563,6 +1546,12 @@ class Compiler : public ErrorSink {
            return reg;
        }

        void setupIntPtrArgs() {
            o4(0xE8BD0002);  // ldmfd   sp!,{r1}
            mStackUse -= 4;
            popType();
        }

        /* Pop TOS to R1
         * Make sure both R0 and TOS are floats. (Could be ints)
         * We know that at least one of R0 and TOS is already a float
@@ -1837,9 +1826,9 @@ class Compiler : public ErrorSink {
        }

        /* load immediate value */
        virtual void li(int i, Type* pType) {
        virtual void li(int i) {
            oad(0xb8, i); /* mov $xx, %eax */
            setR0Type(pType);
            setR0Type(mkpInt);
        }

        virtual void loadFloat(int address, Type* pType) {
@@ -1879,7 +1868,7 @@ class Compiler : public ErrorSink {
            return psym(0x84 + l, t);
        }

        virtual void gcmp(int op, Type* pResultType) {
        virtual void gcmp(int op) {
            Type* pR0Type = getR0Type();
            Type* pTOSType = getTOSType();
            TypeTag tagR0 = pR0Type->tag;
@@ -1890,7 +1879,7 @@ class Compiler : public ErrorSink {
                int t = decodeOp(op);
                o(0x59); /* pop %ecx */
                o(0xc139); /* cmp %eax,%ecx */
                li(0, NULL);
                li(0);
                o(0x0f); /* setxx %al */
                o(t + 0x90);
                o(0xc0);
@@ -1945,7 +1934,7 @@ class Compiler : public ErrorSink {
                }
                o(0xc0b60f); // movzbl %al, %eax
            }
            setR0Type(pResultType);
            setR0Type(mkpInt);
        }

        virtual void genOp(int op) {
@@ -1973,7 +1962,7 @@ class Compiler : public ErrorSink {
                        int size = sizeOf(pR0Type->pHead);
                        if (size != 1) {
                            pushR0();
                            li(size, mkpInt);
                            li(size);
                            // TODO: Optimize for power-of-two.
                            genOp(OP_DIV);
                        }
@@ -2028,7 +2017,7 @@ class Compiler : public ErrorSink {
            }
        }

        virtual void gUnaryCmp(int op, Type* pResultType) {
        virtual void gUnaryCmp(int op) {
            if (op != OP_LOGICAL_NOT) {
                error("Unknown unary cmp %d", op);
            } else {
@@ -2039,7 +2028,7 @@ class Compiler : public ErrorSink {
                            oad(0xb9, 0); /* movl $0, %ecx */
                            int t = decodeOp(op);
                            o(0xc139); /* cmp %eax,%ecx */
                            li(0, NULL);
                            li(0);
                            o(0x0f); /* setxx %al */
                            o(t + 0x90);
                            o(0xc0);
@@ -2062,7 +2051,7 @@ class Compiler : public ErrorSink {
                        break;
                }
            }
            setR0Type(pResultType);
            setR0Type(mkpInt);
        }

        virtual void genUnaryOp(int op) {
@@ -2116,7 +2105,31 @@ class Compiler : public ErrorSink {
            pushType();
        }

        virtual void storeR0ToTOS(Type* pPointerType) {
        virtual void popR0() {
            Type* pR0Type = getR0Type();
            TypeTag r0ct = collapseType(pR0Type->tag);
            switch(r0ct) {
                case TY_INT:
                    o(0x58); /* popl %eax */
                    break;
                case TY_FLOAT:
                    o(0x2404d9); // flds (%esp)
                    o(0x58); /* popl %eax */
                    break;
                case TY_DOUBLE:
                    o(0x2404dd); // fldl (%esp)
                    o(0x58); /* popl %eax */
                    o(0x58); /* popl %eax */
                    break;
                default:
                    error("pushR0 unsupported type %d", r0ct);
                    break;
            }
            popType();
        }

        virtual void storeR0ToTOS() {
            Type* pPointerType = getTOSType();
            assert(pPointerType->tag == TY_POINTER);
            Type* pTargetType = pPointerType->pHead;
            convertR0(pTargetType);
@@ -2141,7 +2154,8 @@ class Compiler : public ErrorSink {
            }
        }

        virtual void loadR0FromR0(Type* pPointerType) {
        virtual void loadR0FromR0() {
            Type* pPointerType = getR0Type();
            assert(pPointerType->tag == TY_POINTER);
            switch (pPointerType->pHead->tag) {
                case TY_INT:
@@ -2204,7 +2218,7 @@ class Compiler : public ErrorSink {
            }
        }

        virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) {
        virtual void loadR0(int ea, Type* pType) {
            TypeTag tag = pType->tag;
            switch (tag) {
                case TY_CHAR:
@@ -2213,22 +2227,10 @@ class Compiler : public ErrorSink {
                    } else {
                        oad(0x85BE0F, ea); // movsbl  ea(%ebp),%eax
                    }
                    if (isIncDec) {
                        error("inc/dec not implemented for char.");
                    }
                    break;
                case TY_INT:
                case TY_POINTER:
                    if (tag == TY_CHAR) {
                    } else {
                    gmov(8, ea); /* mov EA, %eax */
                    }
                    if (isIncDec) {
                        /* Implement post-increment or post decrement.
                         */
                        gmov(0, ea); /* 83 ADD */
                        o(decodeOp(op));
                    }
                    break;
                case TY_FLOAT:
                    if (ea < -LOCAL || ea > LOCAL) {
@@ -2236,9 +2238,6 @@ class Compiler : public ErrorSink {
                    } else {
                        oad(0x85d9, ea); // flds ea(%ebp)
                    }
                    if (isIncDec) {
                        error("inc/dec not implemented for float.");
                    }
                    break;
                case TY_DOUBLE:
                    if (ea < -LOCAL || ea > LOCAL) {
@@ -2246,9 +2245,6 @@ class Compiler : public ErrorSink {
                    } else {
                        oad(0x85dd, ea); // fldl ea(%ebp)
                    }
                    if (isIncDec) {
                        error("inc/dec not implemented for double.");
                    }
                    break;
                default:
                    error("Unable to load type %d", tag);
@@ -2535,9 +2531,9 @@ class Compiler : public ErrorSink {
        }

        /* load immediate value */
        virtual void li(int t, Type* pType) {
        virtual void li(int t) {
            fprintf(stderr, "li(%d)\n", t);
            mpBase->li(t, pType);
            mpBase->li(t);
        }

        virtual void loadFloat(int address, Type* pType) {
@@ -2558,9 +2554,9 @@ class Compiler : public ErrorSink {
            return result;
        }

        virtual void gcmp(int op, Type* pResultType) {
            fprintf(stderr, "gcmp(%d, pResultType)\n", op);
            mpBase->gcmp(op, pResultType);
        virtual void gcmp(int op) {
            fprintf(stderr, "gcmp(%d)\n", op);
            mpBase->gcmp(op);
        }

        virtual void genOp(int op) {
@@ -2569,9 +2565,9 @@ class Compiler : public ErrorSink {
        }


        virtual void gUnaryCmp(int op, Type* pResultType) {
            fprintf(stderr, "gUnaryCmp(%d, pResultType)\n", op);
            mpBase->gUnaryCmp(op, pResultType);
        virtual void gUnaryCmp(int op) {
            fprintf(stderr, "gUnaryCmp(%d)\n", op);
            mpBase->gUnaryCmp(op);
        }

        virtual void genUnaryOp(int op) {
@@ -2584,14 +2580,19 @@ class Compiler : public ErrorSink {
            mpBase->pushR0();
        }

        virtual void storeR0ToTOS(Type* pPointerType) {
            fprintf(stderr, "storeR0ToTOS(%d)\n", pPointerType->pHead->tag);
            mpBase->storeR0ToTOS(pPointerType);
        virtual void popR0() {
            fprintf(stderr, "popR0()\n");
            mpBase->popR0();
        }

        virtual void loadR0FromR0(Type* pPointerType) {
            fprintf(stderr, "loadR0FromR0(%d)\n", pPointerType->pHead->tag);
            mpBase->loadR0FromR0(pPointerType);
        virtual void storeR0ToTOS() {
            fprintf(stderr, "storeR0ToTOS()\n");
            mpBase->storeR0ToTOS();
        }

        virtual void loadR0FromR0() {
            fprintf(stderr, "loadR0FromR0()\n");
            mpBase->loadR0FromR0();
        }

        virtual void leaR0(int ea, Type* pPointerType) {
@@ -2604,9 +2605,9 @@ class Compiler : public ErrorSink {
            mpBase->storeR0(ea, pType);
        }

        virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) {
            fprintf(stderr, "loadR0(%d, %d, %d, pType)\n", ea, isIncDec, op);
            mpBase->loadR0(ea, isIncDec, op, pType);
        virtual void loadR0(int ea, Type* pType) {
            fprintf(stderr, "loadR0(%d, pType)\n", ea);
            mpBase->loadR0(ea, pType);
        }

        virtual void convertR0(Type* pType){
@@ -3814,7 +3815,7 @@ class Compiler : public ErrorSink {

    bool acceptStringLiteral() {
        if (tok == '"') {
            pGen->li((int) glo, mkpCharPtr);
            pGen->leaR0((int) glo, mkpCharPtr);
            // This while loop merges multiple adjacent string constants.
            while (tok == '"') {
                while (ch != '"' && ch != EOF) {
@@ -3869,7 +3870,7 @@ class Compiler : public ErrorSink {
            t = tok;
            next();
            if (t == TOK_NUM) {
                pGen->li(a, mkpInt);
                pGen->li(a);
            } else if (t == TOK_NUM_FLOAT) {
                // Align to 4-byte boundary
                glo = (char*) (((intptr_t) glo + 3) & -4);
@@ -3886,7 +3887,7 @@ class Compiler : public ErrorSink {
                /* -, +, !, ~ */
                unary(false);
                if (t == '!')
                    pGen->gUnaryCmp(a, mkpInt);
                    pGen->gUnaryCmp(a);
                else if (t == '+') {
                    // ignore unary plus.
                } else {
@@ -3917,9 +3918,9 @@ class Compiler : public ErrorSink {
                    if (accept('=')) {
                        pGen->pushR0();
                        expr();
                        pGen->storeR0ToTOS(pR0Type);
                        pGen->storeR0ToTOS();
                    } else if (t) {
                        pGen->loadR0FromR0(pR0Type);
                        pGen->loadR0FromR0();
                    }
                }
                // Else we fall through to the function call below, with
@@ -3965,8 +3966,14 @@ class Compiler : public ErrorSink {
                            error("Undeclared variable %s\n", nameof(t));
                        }
                    }
                    pGen->loadR0(n, tokl == 11, tokc, pVI->pType);
                    // load a variable
                    pGen->loadR0(n, pVI->pType);
                    if (tokl == 11) {
                        // post inc / post dec
                        pGen->pushR0();
                        impInc(tokc);
                        pGen->storeR0(n, pVI->pType);
                        pGen->popR0();
                        next();
                    }
                }
@@ -4037,6 +4044,28 @@ class Compiler : public ErrorSink {
        }
    }

    /* Increment / decrement R0 */

    void impInc(int op) {
        Type* pType = pGen->getR0Type();
        int lit = 1;
        if (op == OP_DECREMENT) {
            lit = -1;
        }
        switch (pType->tag) {
            case TY_INT:
            case TY_CHAR:
            case TY_POINTER:
                pGen->pushR0();
                pGen->li(lit);
                pGen->genOp(OP_PLUS);
                break;
            default:
                error("++/-- illegal for this type.");
                break;
        }
    }

    /* Recursive descent parser for binary operations.
     */
    void binaryOp(int level) {
@@ -4061,10 +4090,10 @@ class Compiler : public ErrorSink {
                    if (pGen->getR0Type() == NULL) {
                        // We failed to parse a right-hand argument.
                        // Push a dummy value so we don't fail
                        pGen->li(0, mkpInt);
                        pGen->li(0);
                    }
                    if ((level == 4) | (level == 5)) {
                        pGen->gcmp(t, mkpInt);
                        pGen->gcmp(t);
                    } else {
                        pGen->genOp(t);
                    }
@@ -4073,10 +4102,10 @@ class Compiler : public ErrorSink {
            /* && and || output code generation */
            if (a && level > 8) {
                a = pGen->gtst(t == OP_LOGICAL_OR, a);
                pGen->li(t != OP_LOGICAL_OR, mkpInt);
                pGen->li(t != OP_LOGICAL_OR);
                pGen->gjmp(5); /* jmp $ + 5 (sizeof li, FIXME for ARM) */
                pGen->gsym(a);
                pGen->li(t == OP_LOGICAL_OR, mkpInt);
                pGen->li(t == OP_LOGICAL_OR);
            }
        }
    }