system/corennnnn
Revision | e7b590666dba83c72b7f7bf210dad7239ab04b4f (tree) |
---|---|
Zeit | 2009-05-21 03:27:04 |
Autor | Jack Palevich <jackpal@goog...> |
Commiter | Jack Palevich |
Implement architecture-dependent defaults.
If libacc is built on x86, then x86 is the default code generator.
If libacc is built on arm. then ARM is the default code generator
And so on for future architectures.
The 64-bit x64 machine has no working code generator currently.
We may add one to support the simulator builds.
Improved the test program so we don't try to run tests if the
compile failed. Also avoid running tests that don't work on
a given platform.
@@ -1,4 +1,15 @@ | ||
1 | 1 | /* |
2 | + * Android "Almost" C Compiler. | |
3 | + * This is a compiler for a small subset of the C language, intended for use | |
4 | + * in scripting environments where speed and memory footprint are important. | |
5 | + * | |
6 | + * This code is based upon the "unobfuscated" version of the | |
7 | + * Obfuscated Tiny C compiler, and retains the | |
8 | + * original copyright notice and license from that compiler, see below. | |
9 | + * | |
10 | + */ | |
11 | + | |
12 | +/* | |
2 | 13 | Obfuscated Tiny C Compiler |
3 | 14 | |
4 | 15 | Copyright (C) 2001-2003 Fabrice Bellard |
@@ -31,11 +42,24 @@ | ||
31 | 42 | #include <unistd.h> |
32 | 43 | #endif |
33 | 44 | |
45 | +#if defined(__arm__) | |
46 | +#define DEFAULT_ARM_CODEGEN | |
47 | +#elif defined(__i386__) | |
48 | +#define DEFAULT_X86_CODEGEN | |
49 | +#elif defined(__x86_64__) | |
50 | +#define DEFAULT_X64_CODEGEN | |
51 | +#endif | |
52 | + | |
53 | +#define PROVIDE_X86_CODEGEN | |
54 | +#define PROVIDE_ARM_CODEGEN | |
55 | + | |
56 | +#ifdef PROVIDE_ARM_CODEGEN | |
34 | 57 | #include "disassem.h" |
58 | +#endif | |
35 | 59 | |
36 | 60 | namespace acc { |
37 | 61 | |
38 | -class compiler { | |
62 | +class Compiler { | |
39 | 63 | class CodeBuf { |
40 | 64 | char* ind; |
41 | 65 | char* pProgramBase; |
@@ -63,14 +87,6 @@ class compiler { | ||
63 | 87 | ind = pProgramBase; |
64 | 88 | } |
65 | 89 | |
66 | - void o(int n) { | |
67 | - /* cannot use unsigned, so we must do a hack */ | |
68 | - while (n && n != -1) { | |
69 | - *ind++ = n; | |
70 | - n = n >> 8; | |
71 | - } | |
72 | - } | |
73 | - | |
74 | 90 | int o4(int n) { |
75 | 91 | int result = (int) ind; |
76 | 92 | * (int*) ind = n; |
@@ -85,31 +101,6 @@ class compiler { | ||
85 | 101 | *ind++ = n; |
86 | 102 | } |
87 | 103 | |
88 | - /* output a symbol and patch all calls to it */ | |
89 | - void gsym(int t) { | |
90 | - int n; | |
91 | - while (t) { | |
92 | - n = *(int *) t; /* next value */ | |
93 | - *(int *) t = ((int) ind) - t - 4; | |
94 | - t = n; | |
95 | - } | |
96 | - } | |
97 | - | |
98 | - /* psym is used to put an instruction with a data field which is a | |
99 | - reference to a symbol. It is in fact the same as oad ! */ | |
100 | - int psym(int n, int t) { | |
101 | - return oad(n, t); | |
102 | - } | |
103 | - | |
104 | - /* instruction + address */ | |
105 | - int oad(int n, int t) { | |
106 | - o(n); | |
107 | - *(int *) ind = t; | |
108 | - t = (int) ind; | |
109 | - ind = ind + 4; | |
110 | - return t; | |
111 | - } | |
112 | - | |
113 | 104 | inline void* getBase() { |
114 | 105 | return (void*) pProgramBase; |
115 | 106 | } |
@@ -184,9 +175,7 @@ class compiler { | ||
184 | 175 | virtual int disassemble(FILE* out) = 0; |
185 | 176 | |
186 | 177 | /* output a symbol and patch all calls to it */ |
187 | - virtual void gsym(int t) { | |
188 | - pCodeBuf->gsym(t); | |
189 | - } | |
178 | + virtual void gsym(int t) = 0; | |
190 | 179 | |
191 | 180 | virtual int finishCompile() { |
192 | 181 | #if defined(__arm__) |
@@ -205,10 +194,6 @@ class compiler { | ||
205 | 194 | virtual int jumpOffset() = 0; |
206 | 195 | |
207 | 196 | protected: |
208 | - void o(int n) { | |
209 | - pCodeBuf->o(n); | |
210 | - } | |
211 | - | |
212 | 197 | /* |
213 | 198 | * Output a byte. Handles all values, 0..ff. |
214 | 199 | */ |
@@ -216,15 +201,8 @@ class compiler { | ||
216 | 201 | pCodeBuf->ob(n); |
217 | 202 | } |
218 | 203 | |
219 | - /* psym is used to put an instruction with a data field which is a | |
220 | - reference to a symbol. It is in fact the same as oad ! */ | |
221 | - int psym(int n, int t) { | |
222 | - return oad(n, t); | |
223 | - } | |
224 | - | |
225 | - /* instruction + address */ | |
226 | - int oad(int n, int t) { | |
227 | - return pCodeBuf->oad(n,t); | |
204 | + int o4(int data) { | |
205 | + return pCodeBuf->o4(data); | |
228 | 206 | } |
229 | 207 | |
230 | 208 | int getBase() { |
@@ -234,14 +212,12 @@ class compiler { | ||
234 | 212 | int getPC() { |
235 | 213 | return pCodeBuf->getPC(); |
236 | 214 | } |
237 | - | |
238 | - int o4(int data) { | |
239 | - return pCodeBuf->o4(data); | |
240 | - } | |
241 | 215 | private: |
242 | 216 | CodeBuf* pCodeBuf; |
243 | 217 | }; |
244 | 218 | |
219 | +#ifdef PROVIDE_ARM_CODEGEN | |
220 | + | |
245 | 221 | class ARMCodeGenerator : public CodeGenerator { |
246 | 222 | public: |
247 | 223 | ARMCodeGenerator() {} |
@@ -701,6 +677,10 @@ class compiler { | ||
701 | 677 | } |
702 | 678 | }; |
703 | 679 | |
680 | +#endif // PROVIDE_X86_CODEGEN | |
681 | + | |
682 | +#ifdef PROVIDE_X86_CODEGEN | |
683 | + | |
704 | 684 | class X86CodeGenerator : public CodeGenerator { |
705 | 685 | public: |
706 | 686 | X86CodeGenerator() {} |
@@ -829,7 +809,45 @@ class compiler { | ||
829 | 809 | return 1; |
830 | 810 | } |
831 | 811 | |
812 | + /* output a symbol and patch all calls to it */ | |
813 | + virtual void gsym(int t) { | |
814 | + int n; | |
815 | + int pc = getPC(); | |
816 | + while (t) { | |
817 | + n = *(int *) t; /* next value */ | |
818 | + *(int *) t = pc - t - 4; | |
819 | + t = n; | |
820 | + } | |
821 | + } | |
822 | + | |
832 | 823 | private: |
824 | + | |
825 | + /** Output 1 to 4 bytes. | |
826 | + * | |
827 | + */ | |
828 | + void o(int n) { | |
829 | + /* cannot use unsigned, so we must do a hack */ | |
830 | + while (n && n != -1) { | |
831 | + ob(n & 0xff); | |
832 | + n = n >> 8; | |
833 | + } | |
834 | + } | |
835 | + | |
836 | + /* psym is used to put an instruction with a data field which is a | |
837 | + reference to a symbol. It is in fact the same as oad ! */ | |
838 | + int psym(int n, int t) { | |
839 | + return oad(n, t); | |
840 | + } | |
841 | + | |
842 | + /* instruction + address */ | |
843 | + int oad(int n, int t) { | |
844 | + o(n); | |
845 | + int result = getPC(); | |
846 | + o4(t); | |
847 | + return result; | |
848 | + } | |
849 | + | |
850 | + | |
833 | 851 | static const int operatorHelper[]; |
834 | 852 | |
835 | 853 | int decodeOp(int op) { |
@@ -846,6 +864,8 @@ class compiler { | ||
846 | 864 | } |
847 | 865 | }; |
848 | 866 | |
867 | +#endif // PROVIDE_X86_CODEGEN | |
868 | + | |
849 | 869 | /* vars: value of variables |
850 | 870 | loc : local variable index |
851 | 871 | glo : global variable index |
@@ -1426,16 +1446,31 @@ class compiler { | ||
1426 | 1446 | |
1427 | 1447 | if (architecture != NULL) { |
1428 | 1448 | if (strcmp(architecture, "arm") == 0) { |
1449 | +#ifdef PROVIDE_ARM_CODEGEN | |
1429 | 1450 | pGen = new ARMCodeGenerator(); |
1451 | +#else | |
1452 | + fprintf(stderr, "Unsupported architecture %s", architecture); | |
1453 | +#endif | |
1430 | 1454 | } else if (strcmp(architecture, "x86") == 0) { |
1455 | +#ifdef PROVIDE_X86_CODEGEN | |
1431 | 1456 | pGen = new X86CodeGenerator(); |
1457 | +#else | |
1458 | + fprintf(stderr, "Unsupported architecture %s", architecture); | |
1459 | +#endif | |
1432 | 1460 | } else { |
1433 | 1461 | fprintf(stderr, "Unknown architecture %s", architecture); |
1434 | 1462 | } |
1435 | 1463 | } |
1436 | 1464 | |
1437 | 1465 | if (pGen == NULL) { |
1466 | +#if defined(DEFAULT_ARM_CODEGEN) | |
1438 | 1467 | pGen = new ARMCodeGenerator(); |
1468 | +#elif defined(DEFAULT_X86_CODEGEN) | |
1469 | + pGen = new X86CodeGenerator(); | |
1470 | +#endif | |
1471 | + } | |
1472 | + if (pGen == NULL) { | |
1473 | + fprintf(stderr, "No code generator defined."); | |
1439 | 1474 | } |
1440 | 1475 | } |
1441 | 1476 |
@@ -1447,11 +1482,11 @@ public: | ||
1447 | 1482 | const char* architecture; |
1448 | 1483 | }; |
1449 | 1484 | |
1450 | - compiler() { | |
1485 | + Compiler() { | |
1451 | 1486 | clear(); |
1452 | 1487 | } |
1453 | 1488 | |
1454 | - ~compiler() { | |
1489 | + ~Compiler() { | |
1455 | 1490 | cleanup(); |
1456 | 1491 | } |
1457 | 1492 |
@@ -1498,10 +1533,10 @@ public: | ||
1498 | 1533 | |
1499 | 1534 | }; |
1500 | 1535 | |
1501 | -const char* compiler::operatorChars = | |
1536 | +const char* Compiler::operatorChars = | |
1502 | 1537 | "++--*@/@%@+@-@<<>><=>=<@>@==!=&&||&@^@|@~@!@"; |
1503 | 1538 | |
1504 | -const char compiler::operatorLevel[] = | |
1539 | +const char Compiler::operatorLevel[] = | |
1505 | 1540 | {11, 11, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, |
1506 | 1541 | 5, 5, /* ==, != */ |
1507 | 1542 | 9, 10, /* &&, || */ |
@@ -1509,9 +1544,9 @@ const char compiler::operatorLevel[] = | ||
1509 | 1544 | 2, 2 /* ~ ! */ |
1510 | 1545 | }; |
1511 | 1546 | |
1512 | -FILE* compiler::ARMCodeGenerator::disasmOut; | |
1547 | +FILE* Compiler::ARMCodeGenerator::disasmOut; | |
1513 | 1548 | |
1514 | -const int compiler::X86CodeGenerator::operatorHelper[] = { | |
1549 | +const int Compiler::X86CodeGenerator::operatorHelper[] = { | |
1515 | 1550 | 0x1, // ++ |
1516 | 1551 | 0xff, // -- |
1517 | 1552 | 0xc1af0f, // * |
@@ -1539,7 +1574,7 @@ const int compiler::X86CodeGenerator::operatorHelper[] = { | ||
1539 | 1574 | } // namespace acc |
1540 | 1575 | |
1541 | 1576 | // This is a separate function so it can easily be set by breakpoint in gdb. |
1542 | -int run(acc::compiler& c, int argc, char** argv) { | |
1577 | +int run(acc::Compiler& c, int argc, char** argv) { | |
1543 | 1578 | return c.run(argc, argv); |
1544 | 1579 | } |
1545 | 1580 |
@@ -1548,7 +1583,7 @@ int main(int argc, char** argv) { | ||
1548 | 1583 | bool doDisassemble = false; |
1549 | 1584 | const char* inFile = NULL; |
1550 | 1585 | const char* outFile = NULL; |
1551 | - const char* architecture = "arm"; | |
1586 | + const char* architecture = NULL; | |
1552 | 1587 | int i; |
1553 | 1588 | for (i = 1; i < argc; i++) { |
1554 | 1589 | char* arg = argv[i]; |
@@ -1593,9 +1628,11 @@ int main(int argc, char** argv) { | ||
1593 | 1628 | return 1; |
1594 | 1629 | } |
1595 | 1630 | } |
1596 | - acc::compiler compiler; | |
1597 | - acc::compiler::args args; | |
1598 | - args.architecture = architecture; | |
1631 | + acc::Compiler compiler; | |
1632 | + acc::Compiler::args args; | |
1633 | + if (architecture != NULL) { | |
1634 | + args.architecture = architecture; | |
1635 | + } | |
1599 | 1636 | int compileResult = compiler.compile(in, args); |
1600 | 1637 | if (in != stdin) { |
1601 | 1638 | fclose(in); |
@@ -1,3 +1,13 @@ | ||
1 | 1 | #!/bin/sh |
2 | +rm -f tests/acc | |
2 | 3 | g++ acc.cpp disassem.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 |
3 | -tests/acc -S tests/returnval.c | |
4 | +if [ -x "tests/acc" ]; then | |
5 | + tests/acc -S tests/returnval.c | |
6 | + | |
7 | + if [ "$(uname)" = "Linux" ]; then | |
8 | + if [ "$(uname -m)" = "i686" ]; then | |
9 | + echo "Linux i686. Testing otcc.c" | |
10 | + tests/acc tests/otcc.c tests/otcc.c tests/returnval.c | |
11 | + fi | |
12 | + fi | |
13 | +fi |