diff options
| author | Android (Google) Code Review <android-gerrit@google.com> | 2009-05-13 19:53:32 -0700 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2009-05-13 19:53:32 -0700 |
| commit | 2ae648f0126c6dcb775c2a84c067c349761809b6 (patch) | |
| tree | 4e8de11054281940c7e4af55df545b38c82de28e | |
| parent | a6986aa8e8345f86c0c2511e9598025fc9195904 (diff) | |
| parent | 546b2249eff4d95622c4bab0698ebf290c9ed836 (diff) | |
| download | system_core-2ae648f0126c6dcb775c2a84c067c349761809b6.zip system_core-2ae648f0126c6dcb775c2a84c067c349761809b6.tar.gz system_core-2ae648f0126c6dcb775c2a84c067c349761809b6.tar.bz2 | |
Merge change 1628
* changes:
Begin filling in ARM code generator.
| -rw-r--r-- | libacc/Android.mk | 11 | ||||
| -rw-r--r-- | libacc/acc.cpp | 134 | ||||
| -rwxr-xr-x | libacc/test | 2 | ||||
| -rw-r--r-- | libacc/tests/otcc.out-orig | bin | 8591 -> 8591 bytes |
4 files changed, 110 insertions, 37 deletions
diff --git a/libacc/Android.mk b/libacc/Android.mk new file mode 100644 index 0000000..30f777a --- /dev/null +++ b/libacc/Android.mk @@ -0,0 +1,11 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +# +# Shared library +# + +LOCAL_MODULE:= acc +LOCAL_SRC_FILES := acc.cpp + +include $(BUILD_EXECUTABLE) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 13a863f..0cc1a0f 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -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 void functionExit() { - fprintf(stderr, "functionExit();\n"); - o(0xc3c9); /* leave, ret */ + 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(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; } diff --git a/libacc/test b/libacc/test index be883a6..8bf33c8 100755 --- a/libacc/test +++ b/libacc/test @@ -1,3 +1,3 @@ #!/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 diff --git a/libacc/tests/otcc.out-orig b/libacc/tests/otcc.out-orig Binary files differindex 3bf7e1f..6b8bd59 100644 --- a/libacc/tests/otcc.out-orig +++ b/libacc/tests/otcc.out-orig |
