system/corennnnn
リビジョン | 2ca20190af3582ebb683977386a9188aba3c65df (tree) |
---|---|
日時 | 2009-05-21 03:38:38 |
作者 | Android (Google) Code Review <android-gerrit@goog...> |
コミッター | Android (Google) Code Review |
Merge change 2096
* changes:
@@ -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 |