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

Commit b6154509 authored by Jack Palevich's avatar Jack Palevich
Browse files

Implement arrays.

Added check to see that pointer types are compatible when passing function
arguments.
parent aa027b46
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__':