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

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

Merge change 20014

* changes:
  Implement arrays.
parents 2b9a6ce0 b6154509
Loading
Loading
Loading
Loading
+175 −36
Original line number Diff line number Diff line
@@ -148,7 +148,8 @@ class Compiler : public ErrorSink {

    struct Type {
        TypeTag tag;
        tokenid_t id; // For function arguments (stores length for array)
        tokenid_t id; // For function arguments, local vars
        int length; // length of array
        Type* pHead;
        Type* pTail;
    };
@@ -405,7 +406,16 @@ class Compiler : public ErrorSink {
        /**
         * Convert R0 to the given type.
         */
        virtual void convertR0(Type* pType) = 0;

        void convertR0(Type* pType) {
            convertR0Imp(pType, false);
        }

        void castR0(Type* pType) {
            convertR0Imp(pType, true);
        }

        virtual void convertR0Imp(Type* pType, bool isCast) = 0;

        /* Emit code to adjust the stack for a function call. Return the
         * label for the address of the instruction that adjusts the
@@ -622,14 +632,40 @@ class Compiler : public ErrorSink {
            return collapseType(getR0Type()->tag);
        }

        bool isFloatType(Type* pType) {
        static bool isFloatType(Type* pType) {
            return isFloatTag(pType->tag);
        }

        bool isFloatTag(TypeTag tag) {
        static bool isFloatTag(TypeTag tag) {
            return tag == TY_FLOAT || tag == TY_DOUBLE;
        }

        static bool isPointerType(Type* pType) {
            return isPointerTag(pType->tag);
        }

        static bool isPointerTag(TypeTag tag) {
            return tag == TY_POINTER || tag == TY_ARRAY;
        }

        Type* getPointerArithmeticResultType(Type* a, Type* b) {
            TypeTag aTag = a->tag;
            TypeTag bTag = b->tag;
            if (aTag == TY_POINTER) {
                return a;
            }
            if (bTag == TY_POINTER) {
                return b;
            }
            if (aTag == TY_ARRAY) {
                return a->pTail;
            }
            if (bTag == TY_ARRAY) {
                return b->pTail;
            }
            return NULL;
        }

        Type* mkpInt;

    private:
@@ -848,8 +884,8 @@ class Compiler : public ErrorSink {
            bool isFloatTOS = isFloatTag(tagTOS);
            if (!isFloatR0 && !isFloatTOS) {
                setupIntPtrArgs();
                bool isPtrR0 = tagR0 == TY_POINTER;
                bool isPtrTOS = tagTOS == TY_POINTER;
                bool isPtrR0 = isPointerTag(tagR0);
                bool isPtrTOS = isPointerTag(tagTOS);
                if (isPtrR0 || isPtrTOS) {
                    if (isPtrR0 && isPtrTOS) {
                        if (op != OP_MINUS) {
@@ -871,7 +907,8 @@ class Compiler : public ErrorSink {
                        if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) {
                            error("Unsupported pointer-scalar operation %d", op);
                        }
                        Type* pPtrType = isPtrR0 ? pR0Type : pTOSType;
                        Type* pPtrType = getPointerArithmeticResultType(
                                pR0Type, pTOSType);
                        int size = sizeOf(pPtrType->pHead);
                        if (size != 1) {
                            // TODO: Optimize for power-of-two.
@@ -1131,7 +1168,8 @@ class Compiler : public ErrorSink {
        virtual void loadR0FromR0() {
            Type* pPointerType = getR0Type();
            assert(pPointerType->tag == TY_POINTER);
            switch (pPointerType->pHead->tag) {
            TypeTag tag = pPointerType->pHead->tag;
            switch (tag) {
                case TY_POINTER:
                case TY_INT:
                case TY_FLOAT:
@@ -1147,7 +1185,7 @@ class Compiler : public ErrorSink {
                    o4(0xE1C000D0); // ldrd   r0, [r0]
                    break;
                default:
                    error("loadR0FromR0: unimplemented type");
                    error("loadR0FromR0: unimplemented type %d", tag);
                    break;
            }
            setR0Type(pPointerType->pHead);
@@ -1197,9 +1235,27 @@ class Compiler : public ErrorSink {
            return result;
        }

        virtual void convertR0(Type* pType){
        virtual void convertR0Imp(Type* pType, bool isCast){
            Type* pR0Type = getR0Type();
            if (bitsSame(pType, pR0Type)) {
            if (isPointerType(pType) && isPointerType(pR0Type)) {
                Type* pA = pR0Type;
                Type* pB = pType;
                // Array decays to pointer
                if (pA->tag == TY_ARRAY && pB->tag == TY_POINTER) {
                    pA = pA->pTail;
                }
                if (typeEqual(pA, pB)) {
                    return; // OK
                }
                if (pB->pHead->tag == TY_VOID) {
                    return; // convert to void* is OK.
                }
                if (pA->tag == TY_POINTER && pB->tag == TY_POINTER
                        && isCast) {
                    return; // OK
                }
                error("Incompatible pointer or array types");
            } else if (bitsSame(pType, pR0Type)) {
                // do nothing special
            } else {
                TypeTag r0Tag = collapseType(pR0Type->tag);
@@ -1423,14 +1479,17 @@ class Compiler : public ErrorSink {
                    return 2;
                case TY_CHAR:
                    return 1;
                default:
                    return 0;
                case TY_FLOAT:
                    return 4;
                case TY_DOUBLE:
                    return 8;
                case TY_POINTER:
                    return 4;
                case TY_ARRAY:
                    return pType->length * sizeOf(pType->pHead);
                default:
                    error("Unsupported type %d", pType->tag);
                    return 0;
            }
        }

@@ -1438,6 +1497,8 @@ class Compiler : public ErrorSink {
            switch(pType->tag) {
                case TY_DOUBLE:
                    return 8;
                case TY_ARRAY:
                    return stackAlignmentOf(pType->pHead);
                default:
                    return 4;
            }
@@ -1447,6 +1508,11 @@ class Compiler : public ErrorSink {
            switch(pType->tag) {
                case TY_DOUBLE:
                    return 8;
                case TY_ARRAY:
                    return sizeOf(pType);
                case TY_FUNC:
                    error("stackSizeOf func not supported");
                    return 4;
                default:
                    return 4;
            }
@@ -1911,8 +1977,8 @@ class Compiler : public ErrorSink {
            bool isFloatR0 = isFloatTag(tagR0);
            bool isFloatTOS = isFloatTag(tagTOS);
            if (!isFloatR0 && !isFloatTOS) {
                bool isPtrR0 = tagR0 == TY_POINTER;
                bool isPtrTOS = tagTOS == TY_POINTER;
                bool isPtrR0 = isPointerTag(tagR0);
                bool isPtrTOS = isPointerTag(tagTOS);
                if (isPtrR0 || isPtrTOS) {
                    if (isPtrR0 && isPtrTOS) {
                        if (op != OP_MINUS) {
@@ -1936,7 +2002,8 @@ class Compiler : public ErrorSink {
                        if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) {
                            error("Unsupported pointer-scalar operation %d", op);
                        }
                        Type* pPtrType = isPtrR0 ? pR0Type : pTOSType;
                        Type* pPtrType = getPointerArithmeticResultType(
                                pR0Type, pTOSType);
                        o(0x59); /* pop %ecx */
                        int size = sizeOf(pPtrType->pHead);
                        if (size != 1) {
@@ -2146,7 +2213,8 @@ class Compiler : public ErrorSink {
        virtual void loadR0FromR0() {
            Type* pPointerType = getR0Type();
            assert(pPointerType->tag == TY_POINTER);
            switch (pPointerType->pHead->tag) {
            TypeTag tag = pPointerType->pHead->tag;
            switch (tag) {
                case TY_POINTER:
                case TY_INT:
                    o2(0x008b); /* mov (%eax), %eax */
@@ -2166,7 +2234,7 @@ class Compiler : public ErrorSink {
                    o2(0x00dd); // fldl (%eax)
                    break;
                default:
                    error("loadR0FromR0: unsupported type");
                    error("loadR0FromR0: unsupported type %d", tag);
                    break;
            }
            setR0Type(pPointerType->pHead);
@@ -2183,14 +2251,32 @@ class Compiler : public ErrorSink {
            return getPC() - 4;
        }

        virtual void convertR0(Type* pType){
        virtual void convertR0Imp(Type* pType, bool isCast){
            Type* pR0Type = getR0Type();
            if (pR0Type == NULL) {
                assert(false);
                setR0Type(pType);
                return;
            }
            if (bitsSame(pType, pR0Type)) {
            if (isPointerType(pType) && isPointerType(pR0Type)) {
                Type* pA = pR0Type;
                Type* pB = pType;
                // Array decays to pointer
                if (pA->tag == TY_ARRAY && pB->tag == TY_POINTER) {
                    pA = pA->pTail;
                }
                if (typeEqual(pA, pB)) {
                    return; // OK
                }
                if (pB->pHead->tag == TY_VOID) {
                    return; // convert to void* is OK.
                }
                if (pA->tag == TY_POINTER && pB->tag == TY_POINTER
                        && isCast) {
                    return; // OK
                }
                error("Incompatible pointer or array types");
            } else if (bitsSame(pType, pR0Type)) {
                // do nothing special
            } else if (isFloatType(pType) && isFloatType(pR0Type)) {
                // do nothing special, both held in same register on x87.
@@ -2326,6 +2412,11 @@ class Compiler : public ErrorSink {
                return 1;
            case TY_SHORT:
                return 2;
            case TY_ARRAY:
                return alignmentOf(pType->pHead);
            case TY_FUNC:
                error("alignment of func not supported");
                return 1;
            default:
                return 4;
            }
@@ -2342,14 +2433,17 @@ class Compiler : public ErrorSink {
                    return 2;
                case TY_CHAR:
                    return 1;
                default:
                    return 0;
                case TY_FLOAT:
                    return 4;
                case TY_DOUBLE:
                    return 8;
                case TY_POINTER:
                    return 4;
                case TY_ARRAY:
                    return pType->length * sizeOf(pType->pHead);
                default:
                    error("Unsupported type %d", pType->tag);
                    return 0;
            }
        }

@@ -2361,6 +2455,11 @@ class Compiler : public ErrorSink {
            switch(pType->tag) {
                case TY_DOUBLE:
                    return 8;
                case TY_ARRAY:
                    return sizeOf(pType);
                case TY_FUNC:
                    error("stackSizeOf func not supported");
                    return 4;
                default:
                    return 4;
            }
@@ -3911,7 +4010,7 @@ class Compiler : public ErrorSink {
                    skip(')');
                    unary();
                    pGen->forceR0RVal();
                    pGen->convertR0(pCast);
                    pGen->castR0(pCast);
                } else {
                    commaExpr();
                    skip(')');
@@ -3959,10 +4058,18 @@ class Compiler : public ErrorSink {
                    }
                }
                // load a variable
                Type* pVal = createPtrType(pVI->pType);
                Type* pVal;
                ExpressionType et;
                if (pVI->pType->tag == TY_ARRAY) {
                    pVal = pVI->pType;
                    et = ET_RVALUE;
                } else {
                    pVal = createPtrType(pVI->pType);
                    et = ET_LVALUE;
                }
                if (n) {
                    ExpressionType et = ET_LVALUE;
                    if (pVal->pHead->tag == TY_FUNC) {
                    int tag = pVal->pHead->tag;
                    if (tag == TY_FUNC) {
                        et = ET_RVALUE;
                    }
                    pGen->leaR0(n, pVal, et);
@@ -4251,6 +4358,8 @@ class Compiler : public ErrorSink {
        }
        if (at == TY_POINTER) {
            return typeEqual(a->pHead, b->pHead);
        } else if (at == TY_ARRAY) {
            return a->length == b->length && typeEqual(a->pHead, b->pHead);
        } else if (at == TY_FUNC || at == TY_PARAM) {
            return typeEqual(a->pHead, b->pHead)
                && typeEqual(a->pTail, b->pTail);
@@ -4345,6 +4454,9 @@ class Compiler : public ErrorSink {
                }
                buffer.append('*');
                break;
            case TY_ARRAY:
                decodeTypeImpPrefix(buffer, pType->pHead);
                break;
            case TY_FUNC:
                decodeTypeImp(buffer, pType->pHead);
                break;
@@ -4369,6 +4481,13 @@ class Compiler : public ErrorSink {
                }
                decodeTypeImpPostfix(buffer, pType->pHead);
                break;
            case TY_ARRAY:
                {
                    String temp;
                    temp.printf("[%d]", pType->length);
                    buffer.append(temp);
                }
                break;
            case TY_FUNC:
                buffer.append('(');
                for(Type* pArg = pType->pTail; pArg; pArg = pArg->pTail) {
@@ -4418,9 +4537,13 @@ class Compiler : public ErrorSink {
                                  nameRequired, reportFailure);
        if (declName) {
            // Clone the parent type so we can set a unique ID
            Type* pOldType = pType;
            pType = createType(pType->tag, pType->pHead, pType->pTail);

            pType->id = declName;
            pType->length = pOldType->length;
        } else if (nameRequired) {
            error("Expected a variable name");
        }
        // fprintf(stderr, "Parsed a declaration:       ");
        // printType(pType);
@@ -4490,11 +4613,27 @@ class Compiler : public ErrorSink {
            error("Expected name. Got %s", temp.getUnwrapped());
            reportFailure = true;
        }
        while (accept('(')) {
        for(;;) {
            if (accept('(')) {
                // Function declaration
                Type* pTail = acceptArgs(nameAllowed);
                pType = createType(TY_FUNC, pType, pTail);
                skip(')');
            } if (accept('[')) {
                if (tok != ']') {
                    if (tok != TOK_NUM || tokc <= 0) {
                        error("Expected positive integer constant");
                    } else {
                        Type* pDecayType = createPtrType(pType);
                        pType = createType(TY_ARRAY, pType, pDecayType);
                        pType->length = tokc;
                    }
                    next();
                }
                skip(']');
            } else {
                break;
            }
        }

        if (pNewHead) {
+77 −0
Original line number Diff line number Diff line
// Array allocation tests

void testLocalInt()
{
    int a[3];
    a[0] = 1;
    a[1] = 2;
    a[2] = a[0] + a[1];
    printf("localInt: %d\n", a[2]);
}

char a[3];
double d[3];

void testGlobalChar()
{
    a[0] = 1;
    a[1] = 2;
    a[2] = a[0] + a[1];
    printf("globalChar: %d\n", a[2]);
}

void testGlobalDouble()
{
    d[0] = 1;
    d[1] = 2;
    d[2] = d[0] + d[1];
    printf("globalDouble: %g\n", d[2]);
}

void testLocalDouble()
{
    double d[3];
    float  m[12];
    m[0] = 1.0f;
    m[1] = 2.0f;
    d[0] = 1.0;
    d[1] = 2.0;
    d[2] = d[0] + d[1];
    m[2] = m[0] + m[1];
    printf("localDouble: %g %g\n", d[2], m[2]);
}

void vectorAdd(int* a, int* b, float* c, int len) {
    int i;
    for(i = 0; i < len; i++) {
        c[i] = a[i] + b[i];
    }
}

void testArgs() {
    int a[3], b[3];
    float c[3];
    int i;
    int len = 3;
    for(i = 0; i < len; i++) {
        a[i] = i;
        b[i] = i;
        c[i] = 0;
    }
    vectorAdd(a,b,c, len);
    printf("testArgs:");
    for(i = 0; i < len; i++) {
        printf(" %g", c[i]);
    }
    printf("\n");
}

int main()
{
    testLocalInt();
    testLocalDouble();
    testGlobalChar();
    testGlobalDouble();
    testArgs();
    return 0;
}
+10 −0
Original line number Diff line number Diff line
@@ -385,6 +385,16 @@ result: 0
    def testShort(self):
        self.compileCheck(["-R", "data/short.c"], """Executing compiled code:
result: -2
""","""""")

    def testArray(self):
        self.compileCheck(["-R", "data/array.c"], """Executing compiled code:
localInt: 3
localDouble: 3 3
globalChar: 3
globalDouble: 3
testArgs: 0 2 4
result: 0
""","""""")

if __name__ == '__main__':