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

Commit 1a539db2 authored by Jack Palevich's avatar Jack Palevich
Browse files

Some x86 floating point code works.

We now check the types and number of arguments to a function.
parent 8df4619e
Loading
Loading
Loading
Loading
+130 −61
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@
#define PROVIDE_X64_CODEGEN
#endif


#ifdef PROVIDE_ARM_CODEGEN
#include "disassem.h"
#endif
@@ -297,11 +296,8 @@ class Compiler : public ErrorSink {
        /* load immediate value to R0 */
        virtual void li(int i, Type* pType) = 0;

        /* load floating point immediate value to R0 */
        virtual void lif(float f, Type* pType) = 0;

        /* load double-precision floating point immediate value to R0 */
        virtual void lid(double d, Type* pType) = 0;
        /* Load floating point value from global address. */
        virtual void loadFloat(int address, Type* pType) = 0;

        /* Jump to a target, and return the address of the word that
         * holds the target data, in case it needs to be fixed up later.
@@ -389,8 +385,9 @@ class Compiler : public ErrorSink {
        virtual int beginFunctionCallArguments() = 0;

        /* Emit code to store R0 to the stack at byte offset l.
         * Returns stack size of object (typically 4 or 8 bytes)
         */
        virtual void storeR0ToArg(int l) = 0;
        virtual size_t storeR0ToArg(int l) = 0;

        /* Patch the function call preamble.
         * a is the address returned from beginFunctionCallArguments
@@ -461,6 +458,10 @@ class Compiler : public ErrorSink {
         */
        virtual size_t sizeOf(Type* type) = 0;

        virtual Type* getR0Type() {
            return mExpressionStack.back();
        }

    protected:
        /*
         * Output a byte. Handles all values, 0..ff.
@@ -494,6 +495,7 @@ class Compiler : public ErrorSink {

        void assert(bool test) {
            if (!test) {
                * (char*) 0 = 0;
                error("code generator assertion failed.");
            }
        }
@@ -502,10 +504,6 @@ class Compiler : public ErrorSink {
            mExpressionStack.back() = pType;
        }

        Type* getR0Type() {
            return mExpressionStack.back();
        }

        Type* getTOSType() {
            return mExpressionStack[mExpressionStack.size()-2];
        }
@@ -529,6 +527,15 @@ class Compiler : public ErrorSink {
            return collapsedTag[tag];
        }

        TypeTag collapseTypeR0() {
            return collapseType(getR0Type()->tag);
        }

        bool isFloatType(Type* pType) {
            TypeTag tag = pType->tag;
            return tag == TY_FLOAT || tag == TY_DOUBLE;
        }

    private:
        Vector<Type*> mExpressionStack;
        CodeBuf* pCodeBuf;
@@ -613,16 +620,8 @@ class Compiler : public ErrorSink {
            setR0Type(pType);
        }

        virtual void lif(float f, Type* pType) {
            union { float f; int i; } converter;
            converter.f = f;
            li(converter.i, pType);
        }

        virtual void lid(double d, Type* pType) {
            union { double d; int i[2]; } converter;
            converter.d = d;
            error("lid: unimplemented");
        virtual void loadFloat(int address, Type* pType) {
            error("Unimplemented.\n");
            setR0Type(pType);
        }

@@ -843,7 +842,7 @@ class Compiler : public ErrorSink {
        }

        virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) {
            LOG_API("loadR0(%d, %d, %d);\n", ea, isIncDec, op);
            LOG_API("loadR0(%d, %d, %d, %d);\n", ea, isIncDec, op, pType);
            if (ea < LOCAL) {
                // Local, fp relative
                if (ea < -4095 || ea > 4095) {
@@ -891,10 +890,16 @@ class Compiler : public ErrorSink {
        }

        virtual void convertR0(Type* pType){
            if (bitsSame(pType, getR0Type())) {
                return;
            Type* pR0Type = getR0Type();
            if (bitsSame(pType, pR0Type)) {
                // do nothing special
            } else if (isFloatType(pType) && isFloatType(pR0Type)) {
                // do nothing special, both held in same register on x87.
            } else {
                error("Incompatible types old: %d new: %d",
                      pR0Type->tag, pType->tag);
            }
            error("Incompatible types");
            setR0Type(pType);
        }

        virtual int beginFunctionCallArguments() {
@@ -902,12 +907,13 @@ class Compiler : public ErrorSink {
            return o4(0xE24DDF00); // Placeholder
        }

        virtual void storeR0ToArg(int l) {
        virtual size_t storeR0ToArg(int l) {
            LOG_API("storeR0ToArg(%d);\n", l);
            if (l < 0 || l > 4096-4) {
                error("l out of range for stack offset: 0x%08x", l);
            }
            o4(0xE58D0000 + l); // str r0, [sp, #4]
            return 4;
        }

        virtual void endFunctionCallArguments(int a, int l) {
@@ -1169,18 +1175,19 @@ class Compiler : public ErrorSink {
            setR0Type(pType);
        }

        virtual void lif(float f, Type* pType) {
            union { float f; int i; } converter;
            converter.f = f;
        virtual void loadFloat(int address, Type* pType) {
            setR0Type(pType);
            error("unimplemented: lif");
            switch (pType->tag) {
            case TY_FLOAT:
                oad(0x05D9, address);      // flds
                break;
            case TY_DOUBLE:
                oad(0x05DD, address);      // fldl
                break;
            default:
                assert(false);
                break;
            }

        virtual void lid(double d, Type* pType) {
            union { double d; int i[2]; } converter;
            converter.d = d;
            setR0Type(pType);
            error("unimplemented: lid");
        }

        virtual int gjmp(int t) {
@@ -1287,19 +1294,44 @@ class Compiler : public ErrorSink {
        }

        virtual void convertR0(Type* pType){
            if (bitsSame(pType, getR0Type())) {
            Type* pR0Type = getR0Type();
            if (pR0Type == NULL) {
                error("don't know R0Type");
                setR0Type(pType);
                return;
            }
            error("convertR0: unsupported conversion %d <- %d", pType->tag,
                  getR0Type()->tag);
            if (bitsSame(pType, pR0Type)) {
                // do nothing special
            } else if (isFloatType(pType) && isFloatType(pR0Type)) {
                // do nothing special, both held in same register on x87.
            } else {
                error("Incompatible types old: %d new: %d",
                      pR0Type->tag, pType->tag);
            }
            setR0Type(pType);
        }

        virtual int beginFunctionCallArguments() {
            return oad(0xec81, 0); /* sub $xxx, %esp */
        }

        virtual void storeR0ToArg(int l) {
        virtual size_t storeR0ToArg(int l) {
            Type* pR0Type = getR0Type();
            TypeTag r0ct = collapseType(pR0Type->tag);
            switch(r0ct) {
                case TY_INT:
                    oad(0x248489, l); /* movl %eax, xxx(%esp) */
                    return 4;
                case TY_FLOAT:
                    oad(0x249CD9, l); /* fstps   xxx(%esp) */
                    return 4;
                case TY_DOUBLE:
                    oad(0x249CDD, l); /* fstpl   xxx(%esp) */
                    return 8;
                default:
                    assert(false);
                    return 0;
            }
        }

        virtual void endFunctionCallArguments(int a, int l) {
@@ -1480,14 +1512,9 @@ class Compiler : public ErrorSink {
            mpBase->li(t, pType);
        }

        virtual void lif(float f, Type* pType) {
            fprintf(stderr, "lif(%g)\n", f);
            mpBase->lif(f, pType);
        }

        virtual void lid(double d, Type* pType) {
            fprintf(stderr, "lid(%g)\n", d);
            mpBase->lid(d, pType);
        virtual void loadFloat(int address, Type* pType) {
            fprintf(stderr, "loadFloat(%d, type)\n", address);
            mpBase->loadFloat(address, pType);
        }

        virtual int gjmp(int t) {
@@ -1550,7 +1577,7 @@ class Compiler : public ErrorSink {
        }

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

@@ -1565,9 +1592,9 @@ class Compiler : public ErrorSink {
            return result;
        }

        virtual void storeR0ToArg(int l) {
        virtual size_t storeR0ToArg(int l) {
            fprintf(stderr, "storeR0ToArg(%d)\n", l);
            mpBase->storeR0ToArg(l);
            return mpBase->storeR0ToArg(l);
        }

        virtual void endFunctionCallArguments(int a, int l) {
@@ -1629,6 +1656,10 @@ class Compiler : public ErrorSink {
        virtual size_t sizeOf(Type* pType){
            return mpBase->sizeOf(pType);
        }

        virtual Type* getR0Type() {
            return mpBase->getR0Type();
        }
    };

#endif // PROVIDE_TRACE_CODEGEN
@@ -2185,6 +2216,8 @@ class Compiler : public ErrorSink {
    Type* mkpIntFn;
    Type* mkpIntPtr;
    Type* mkpCharPtr;
    Type* mkpFloatPtr;
    Type* mkpDoublePtr;
    Type* mkpPtrIntFn;

    InputStream* file;
@@ -2742,9 +2775,17 @@ class Compiler : public ErrorSink {
            if (t == TOK_NUM) {
                pGen->li(a, mkpInt);
            } else if (t == TOK_NUM_FLOAT) {
                pGen->lif(ad, mkpFloat);
                // Align to 4-byte boundary
                glo = (char*) (((intptr_t) glo + 3) & -4);
                * (float*) glo = (float) ad;
                pGen->loadFloat((int) glo, mkpFloat);
                glo += 4;
            } else if (t == TOK_NUM_DOUBLE) {
                pGen->lid(ad, mkpDouble);
                // Align to 8-byte boundary
                glo = (char*) (((intptr_t) glo + 7) & -8);
                * (double*) glo = ad;
                pGen->loadFloat((int) glo, mkpDouble);
                glo += 8;
            } else if (c == 2) {
                /* -, +, !, ~ */
                unary(false);
@@ -2807,7 +2848,11 @@ class Compiler : public ErrorSink {
                /* forward reference: try dlsym */
                if (!n) {
                    n = (intptr_t) dlsym(RTLD_DEFAULT, nameof(t));
                    if (tok == '(') {
                        pVI->pType = mkpIntFn;
                    } else {
                        pVI->pType = mkpInt;
                    }
                    pVI->pAddress = (void*) n;
                }
                if ((tok == '=') & allowAssignment) {
@@ -2830,27 +2875,49 @@ class Compiler : public ErrorSink {

        /* function call */
        if (accept('(')) {
            if (n == 1)
            Type* pArgList = NULL;
            VariableInfo* pVI = NULL;
            if (n == 1) { // Indirect function call, push address of fn.
                pArgList = pGen->getR0Type()->pTail;
                pGen->pushR0();

            } else {
                pVI = VI(t);
                pArgList = pVI->pType->pTail;
            }
            bool varArgs = pArgList == NULL;
            /* push args and invert order */
            a = pGen->beginFunctionCallArguments();
            int l = 0;
            while (tok != ')' && tok != EOF) {
                if (! varArgs && !pArgList) {
                    error ("Unexpected argument.");
                }
                expr();
                pGen->storeR0ToArg(l);
                l = l + 4;
                Type* pTargetType;
                if (pArgList) {
                    pTargetType = pArgList->pHead;
                    pArgList = pArgList->pTail;
                } else {
                    pTargetType = pGen->getR0Type();
                    if (pTargetType->tag == TY_FLOAT) {
                        pTargetType = mkpDouble;
                    }
                }
                pGen->convertR0(pTargetType);
                l += pGen->storeR0ToArg(l);
                if (accept(',')) {
                    // fine
                } else if ( tok != ')') {
                    error("Expected ',' or ')'");
                }
            }
            if (! varArgs && pArgList) {
                error ("Expected more argument(s).");
            }
            pGen->endFunctionCallArguments(a, l);
            skip(')');
            if (!n) {
                /* forward reference */
                VariableInfo* pVI = VI(t);
                pVI->pForward = (void*) pGen->callForward((int) pVI->pForward,
                                                          pVI->pType);
            } else if (n == 1) {
@@ -3595,6 +3662,8 @@ public:
        mkpIntFn =  createType(TY_FUNC, mkpInt, NULL, mGlobalArena);
        mkpIntPtr = createPtrType(mkpInt, mGlobalArena);
        mkpCharPtr = createPtrType(mkpChar, mGlobalArena);
        mkpFloatPtr = createPtrType(mkpFloat, mGlobalArena);
        mkpDoublePtr = createPtrType(mkpDouble, mGlobalArena);
        mkpPtrIntFn = createPtrType(mkpIntFn, mGlobalArena);
    }

+6 −0
Original line number Diff line number Diff line

int main() {
    printf("int: %d float: %g double: %g\n", 1, 2.2f, 3.3);

    return 42;
}