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

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

Merge change 1628

* changes:
  Begin filling in ARM code generator.
parents a6986aa8 546b2249
Loading
Loading
Loading
Loading

libacc/Android.mk

0 → 100644
+11 −0
Original line number Diff line number Diff line
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

#
# Shared library
#

LOCAL_MODULE:= acc
LOCAL_SRC_FILES := acc.cpp

include $(BUILD_EXECUTABLE)
+98 −36
Original line number Diff line number Diff line
@@ -27,6 +27,10 @@
#include <stdlib.h>
#include <string.h>

#if defined(__arm__)
#include <unistd.h>
#endif

namespace acc {

class compiler {
@@ -65,6 +69,13 @@ class compiler {
            }
        }

        int o4(int n) {
            int result = (int) ind;
            * (int*) ind = n;
            ind += 4;
            return result;
        }

        /*
         * Output a byte. Handles all values, 0..ff.
         */
@@ -121,12 +132,12 @@ class compiler {

        /* returns address to patch with local variable size
        */
        virtual int functionEntry() = 0;
        virtual int functionEntry(int argCount) = 0;

        virtual void functionExit() = 0;
        virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) = 0;

        /* load immediate value */
        virtual int li(int t) = 0;
        virtual void li(int t) = 0;

        virtual int gjmp(int t) = 0;

@@ -135,7 +146,7 @@ class compiler {

        virtual void gcmp(int op) = 0;

        virtual int genOp(int op) = 0;
        virtual void genOp(int op) = 0;

        virtual void clearECX() = 0;

@@ -172,6 +183,17 @@ class compiler {
            pCodeBuf->gsym(t);
        }

        virtual int finishCompile() {
#if defined(__arm__)
        const long base = long(pCodeBuf->getBase());
        const long curr = base + long(pCodeBuf->getSize());
        int err = cacheflush(base, curr, 0);
        return err;
#else
        return 0;
#endif
        }

    protected:
        void o(int n) {
            pCodeBuf->o(n);
@@ -199,6 +221,9 @@ class compiler {
            return pCodeBuf->getPC();
        }

        int o4(int data) {
            return pCodeBuf->o4(data);
        }
    private:
        CodeBuf* pCodeBuf;
    };
@@ -208,21 +233,43 @@ class compiler {
        ARMCodeGenerator() {}
        virtual ~ARMCodeGenerator() {}

        // The gnu ARM assembler prints the constants in little-endian,
        // but C hexidecimal constants are big-endian. We trick the
        // gnu assembler into putting out big-endian constants by
        // using the -mbig-endian flag when assembling.

        /* returns address to patch with local variable size
        */
        virtual int functionEntry() {
            fprintf(stderr, "functionEntry();\n");
            o(0xe58955); /* push   %ebp, mov %esp, %ebp */
            return oad(0xec81, 0); /* sub $xxx, %esp */
        virtual int functionEntry(int argCount) {
            fprintf(stderr, "functionEntry(%d);\n", argCount);
            /*
              19 0000 E1A0C00D         mov    ip, sp
              20 0004 E92DD800         stmfd    sp!, {fp, ip, lr, pc}
              21 0008 E24CB004         sub    fp, ip, #4
              22 000c E24DD008         sub    sp, sp, #8
            */
            o4(0xE1A0C00D);
            o4(0xE92DD800);
            o4(0xE24CB004);
            return o4(0xE24DD008);
        }

        virtual void functionExit() {
            fprintf(stderr, "functionExit();\n");
            o(0xc3c9); /* leave, ret */
        virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) {
            fprintf(stderr, "functionExit(%d, %d, %d);\n", argCount, localVariableAddress, localVariableSize);
            /*
              23 0010 E24BD00C         sub    sp, fp, #12
              24 0014 E89DA800         ldmfd    sp, {fp, sp, pc}
            */
            o4(0xE24BD00C);
            o4(0xE89DA800);
            if (localVariableSize < 0 || localVariableSize > 255-8) {
                error("LocalVariableSize");
            }
            *(char*) (localVariableAddress) = localVariableSize + 8;
        }

        /* load immediate value */
        virtual int li(int t) {
        virtual void li(int t) {
            fprintf(stderr, "li(%d);\n", t);
            oad(0xb8, t); /* mov $xx, %eax */
        }
@@ -251,7 +298,7 @@ class compiler {
#endif
        }

        virtual int genOp(int op) {
        virtual void genOp(int op) {
            fprintf(stderr, "genOp(%d);\n", op);
#if 0
            o(decodeOp(op));
@@ -352,6 +399,13 @@ class compiler {

    private:

        void error(const char* fmt,...) {
            va_list ap;
            va_start(ap, fmt);
            vfprintf(stderr, fmt, ap);
            va_end(ap);
            exit(12);
        }
    };

    class X86CodeGenerator : public CodeGenerator {
@@ -361,17 +415,18 @@ class compiler {

        /* returns address to patch with local variable size
        */
        virtual int functionEntry() {
        virtual int functionEntry(int argCount) {
            o(0xe58955); /* push   %ebp, mov %esp, %ebp */
            return oad(0xec81, 0); /* sub $xxx, %esp */
        }

        virtual void functionExit() {
        virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) {
            o(0xc3c9); /* leave, ret */
            *(int *) localVariableAddress = localVariableSize; /* save local variables */
        }

        /* load immediate value */
        virtual int li(int t) {
        virtual void li(int t) {
            oad(0xb8, t); /* mov $xx, %eax */
        }

@@ -394,7 +449,7 @@ class compiler {
            o(0xc0);
        }

        virtual int genOp(int op) {
        virtual void genOp(int op) {
            o(decodeOp(op));
            if (op == OP_MOD)
                o(0x92); /* xchg %edx, %eax */
@@ -478,7 +533,7 @@ class compiler {
            return operatorHelper[op];
        }

        int gmov(int l, int t) {
        void gmov(int l, int t) {
            o(l + 0x83);
            oad((t < LOCAL) << 7 | 5, t);
        }
@@ -578,7 +633,7 @@ class compiler {
    }

    int isid() {
        return isalnum(ch) | ch == '_';
        return isalnum(ch) | (ch == '_');
    }

    /* read a character constant */
@@ -593,7 +648,7 @@ class compiler {
    void next() {
        int l, a;

        while (isspace(ch) | ch == '#') {
        while (isspace(ch) | (ch == '#')) {
            if (ch == '#') {
                inp();
                next();
@@ -653,7 +708,7 @@ class compiler {
                tokc = ch;
                inp();
                inp();
            } else if (tok == '/' & ch == '*') {
            } else if ((tok == '/') & (ch == '*')) {
                inp();
                while (ch) {
                    while (ch != '*')
@@ -667,11 +722,11 @@ class compiler {
            } else {
                const char* t = operatorChars;
                int opIndex = 0;
                while (l = *t++) {
                while ((l = *t++) != 0) {
                    a = *t++;
                    tokl = operatorLevel[opIndex];
                    tokc = opIndex;
                    if (l == tok & (a == ch | a == '@')) {
                    if ((l == tok) & ((a == ch) | (a == '@'))) {
#if 0
                        printf("%c%c -> tokl=%d tokc=0x%x\n",
                                l, a, tokl, tokc);
@@ -734,7 +789,7 @@ class compiler {
    /* l is one if '=' parsing wanted (quick hack) */
    void unary(int l) {
        int n, t, a, c;

        t = 0;
        n = 1; /* type of expression 0 = forward, 1 = value, other =
         lvalue */
        if (tok == '\"') {
@@ -745,7 +800,7 @@ class compiler {
                inp();
            }
            *(char *) glo = 0;
            glo = glo + 4 & -4; /* align heap */
            glo = (glo + 4) & -4; /* align heap */
            inp();
            next();
        } else {
@@ -799,7 +854,7 @@ class compiler {
                /* forward reference: try dlsym */
                if (!n)
                    n = (int) dlsym(0, (char*) last_id);
                if (tok == '=' & l) {
                if ((tok == '=') & l) {
                    /* assignment */
                    next();
                    expr();
@@ -850,7 +905,7 @@ class compiler {

    void sum(int l) {
        int t, n, a;

        t = 0;
        if (l-- == 1)
            unary(1);
        else {
@@ -869,7 +924,7 @@ class compiler {
                    sum(l);
                    pGen->popECX();

                    if (l == 4 | l == 5) {
                    if ((l == 4) | (l == 5)) {
                        pGen->gcmp(t);
                    } else {
                        pGen->genOp(t);
@@ -914,7 +969,7 @@ class compiler {
            } else {
                pGen->gsym(a); /* patch if test */
            }
        } else if (tok == TOK_WHILE | tok == TOK_FOR) {
        } else if ((tok == TOK_WHILE) | (tok == TOK_FOR)) {
            t = tok;
            next();
            skip('(');
@@ -968,7 +1023,7 @@ class compiler {
    void decl(int l) {
        int a;

        while (tok == TOK_INT | tok != -1 & !l) {
        while ((tok == TOK_INT) | ((tok != -1) & (!l))) {
            if (tok == TOK_INT) {
                next();
                while (tok != ';') {
@@ -993,6 +1048,7 @@ class compiler {
                next();
                skip('(');
                a = 8;
                int argCount = 0;
                while (tok != ')') {
                    /* read param name and compute offset */
                    *(int *) tok = a;
@@ -1000,14 +1056,14 @@ class compiler {
                    next();
                    if (tok == ',')
                        next();
                    argCount++;
                }
                next(); /* skip ')' */
                rsym = loc = 0;
                a = pGen->functionEntry();
                a = pGen->functionEntry(argCount);
                block(0);
                pGen->gsym(rsym);
                pGen->functionExit();
                *(int *) a = loc; /* save local variables */
                pGen->functionExit(argCount, a, loc);
            }
        }
    }
@@ -1104,6 +1160,7 @@ public:
        inp();
        next();
        decl(0);
        pGen->finishCompile();
        return 0;
    }

@@ -1162,6 +1219,11 @@ const int compiler::X86CodeGenerator::operatorHelper[] = {

} // namespace acc

// This is a separate function so it can easily be set by breakpoint in gdb.
int run(acc::compiler& c, int argc, char** argv) {
    return c.run(argc, argv);
}

int main(int argc, char** argv) {
    bool doDump = false;
    const char* inFile = NULL;
@@ -1232,7 +1294,7 @@ int main(int argc, char** argv) {
        int codeArgc = argc - i + 1;
        char** codeArgv = argv + i - 1;
        codeArgv[0] = (char*) (inFile ? inFile : "stdin");
        int result = compiler.run(codeArgc, codeArgv);
        int result = run(compiler, codeArgc, codeArgv);
        fprintf(stderr, "result: %d\n", result);
        return result;
    }
+1 −1
Original line number Diff line number Diff line
#!/bin/sh
g++ acc.cpp -ldl -o tests/acc && tests/acc tests/otcc.c -a x86 -d tests/otcc.out && diff tests/otcc.out tests/otcc.out-orig
g++ acc.cpp -g -ldl -o tests/acc && tests/acc tests/otcc.c -a x86 -d tests/otcc.out && diff tests/otcc.out tests/otcc.out-orig
tests/acc tests/simplest.c
(8.39 KiB)

File changed.

No diff preview for this file type.