system/corennnnn
修訂 | 45431bc2528246f829383abda8c2cd72c57fcb65 (tree) |
---|---|
時間 | 2009-07-14 07:57:26 |
作者 | Jack Palevich <jackpal@goog...> |
Commiter | Jack Palevich |
Implement general casts and pointer dereferencing.
Prior to this casts and pointer dereferencing were special-cased.
@@ -1019,6 +1019,7 @@ class Compiler : public ErrorSink { | ||
1019 | 1019 | LOG_API("storeR0(%d);\n", ea); |
1020 | 1020 | TypeTag tag = pType->tag; |
1021 | 1021 | switch (tag) { |
1022 | + case TY_POINTER: | |
1022 | 1023 | case TY_INT: |
1023 | 1024 | case TY_FLOAT: |
1024 | 1025 | if (ea > -LOCAL && ea < LOCAL) { |
@@ -2027,6 +2028,7 @@ class Compiler : public ErrorSink { | ||
2027 | 2028 | TypeTag tag = pType->tag; |
2028 | 2029 | switch (tag) { |
2029 | 2030 | case TY_INT: |
2031 | + case TY_POINTER: | |
2030 | 2032 | gmov(6, ea); /* mov %eax, EA */ |
2031 | 2033 | break; |
2032 | 2034 | case TY_FLOAT: |
@@ -3663,41 +3665,34 @@ class Compiler : public ErrorSink { | ||
3663 | 3665 | pGen->genUnaryOp(a); |
3664 | 3666 | } |
3665 | 3667 | } else if (t == '(') { |
3666 | - expr(); | |
3667 | - skip(')'); | |
3668 | - } else if (t == '*') { | |
3669 | - /* This is a pointer dereference, but we currently only | |
3670 | - * support a pointer dereference if it's immediately | |
3671 | - * in front of a cast. So parse the cast right here. | |
3672 | - */ | |
3673 | - skip('('); | |
3674 | - Type* pCast = expectCastTypeDeclaration(mLocalArena); | |
3675 | - // We currently only handle 3 types of cast: | |
3676 | - // (int*), (char*) , (int (*)()) | |
3677 | - if(typeEqual(pCast, mkpIntPtr)) { | |
3678 | - t = TOK_INT; | |
3679 | - } else if (typeEqual(pCast, mkpCharPtr)) { | |
3680 | - t = TOK_CHAR; | |
3681 | - } else if (typeEqual(pCast, mkpFloatPtr)) { | |
3682 | - t = TOK_FLOAT; | |
3683 | - } else if (typeEqual(pCast, mkpDoublePtr)) { | |
3684 | - t = TOK_DOUBLE; | |
3685 | - } else if (typeEqual(pCast, mkpPtrIntFn)){ | |
3686 | - t = 0; | |
3668 | + // It's either a cast or an expression | |
3669 | + Type* pCast = acceptCastTypeDeclaration(mLocalArena); | |
3670 | + if (pCast) { | |
3671 | + skip(')'); | |
3672 | + unary(false); | |
3673 | + pGen->convertR0(pCast); | |
3687 | 3674 | } else { |
3688 | - String buffer; | |
3689 | - decodeType(buffer, pCast); | |
3690 | - error("Unsupported cast type %s", buffer.getUnwrapped()); | |
3691 | - decodeType(buffer, mkpPtrIntFn); | |
3675 | + expr(); | |
3676 | + skip(')'); | |
3692 | 3677 | } |
3693 | - skip(')'); | |
3678 | + } else if (t == '*') { | |
3679 | + /* This is a pointer dereference. | |
3680 | + */ | |
3694 | 3681 | unary(false); |
3695 | - if (accept('=')) { | |
3696 | - pGen->pushR0(); | |
3697 | - expr(); | |
3698 | - pGen->storeR0ToTOS(pCast); | |
3699 | - } else if (t) { | |
3700 | - pGen->loadR0FromR0(pCast); | |
3682 | + Type* pR0Type = pGen->getR0Type(); | |
3683 | + if (pR0Type->tag != TY_POINTER) { | |
3684 | + error("Expected a pointer type."); | |
3685 | + } else { | |
3686 | + if (pR0Type->pHead->tag == TY_FUNC) { | |
3687 | + t = 0; | |
3688 | + } | |
3689 | + if (accept('=')) { | |
3690 | + pGen->pushR0(); | |
3691 | + expr(); | |
3692 | + pGen->storeR0ToTOS(pR0Type); | |
3693 | + } else if (t) { | |
3694 | + pGen->loadR0FromR0(pR0Type); | |
3695 | + } | |
3701 | 3696 | } |
3702 | 3697 | // Else we fall through to the function call below, with |
3703 | 3698 | // t == 0 to trigger an indirect function call. Hack! |
@@ -0,0 +1,85 @@ | ||
1 | +void test1() { | |
2 | + int a = 3; | |
3 | + int* pb = &a; | |
4 | + int c = *pb; | |
5 | + printf("Reading from a pointer: %d %d\n", a, c); | |
6 | + *pb = 4; | |
7 | + printf("Writing to a pointer: %d\n", a); | |
8 | + printf("Testing casts: %d %g %g %d\n", 3, (float) 3, 4.5, (int) 4.5); | |
9 | +} | |
10 | + | |
11 | +void test2() { | |
12 | + int x = 4; | |
13 | + int px = &x; | |
14 | + // int z = * px; // An error, expected a pointer type | |
15 | + int y = * (int*) px; | |
16 | + printf("Testing reading (int*): %d\n", y); | |
17 | +} | |
18 | + | |
19 | +void test3() { | |
20 | + int px = (int) malloc(120); | |
21 | + * (int*) px = 8; | |
22 | + * (int*) (px + 4) = 9; | |
23 | + printf("Testing writing (int*): %d %d\n", * (int*) px, * (int*) (px + 4)); | |
24 | + free((void*) px); | |
25 | +} | |
26 | + | |
27 | +void test4() { | |
28 | + int x = 0x12345678; | |
29 | + int px = &x; | |
30 | + int a = * (char*) px; | |
31 | + int b = * (char*) (px + 1); | |
32 | + int c = * (char*) (px + 2); | |
33 | + int d = * (char*) (px + 3); | |
34 | + printf("Testing reading (char*): 0x%02x 0x%02x 0x%02x 0x%02x\n", a, b, c, d); | |
35 | +} | |
36 | + | |
37 | +void test5() { | |
38 | + int x = 0xFFFFFFFF; | |
39 | + int px = &x; | |
40 | + * (char*) px = 0x21; | |
41 | + * (char*) (px + 1) = 0x43; | |
42 | + * (char*) (px + 2) = 0x65; | |
43 | + * (char*) (px + 3) = 0x87; | |
44 | + printf("Testing writing (char*): 0x%08x\n", x); | |
45 | +} | |
46 | + | |
47 | +int f(int b) { | |
48 | + printf("f(%d)\n", b); | |
49 | + return 7 * b; | |
50 | +} | |
51 | + | |
52 | +void test6() { | |
53 | + int fp = &f; | |
54 | + int x = (*(int(*)()) fp)(10); | |
55 | + printf("Function pointer result: %d\n", x); | |
56 | +} | |
57 | + | |
58 | +void test7() { | |
59 | + int px = (int) malloc(120); | |
60 | + * (float*) px = 8.8f; | |
61 | + * (float*) (px + 4) = 9.9f; | |
62 | + printf("Testing read/write (float*): %g %g\n", * (float*) px, * (float*) (px + 4)); | |
63 | + free((void*) px); | |
64 | +} | |
65 | + | |
66 | +void test8() { | |
67 | + int px = (int) malloc(120); | |
68 | + * (double*) px = 8.8; | |
69 | + * (double*) (px + 8) = 9.9; | |
70 | + printf("Testing read/write (double*): %g %g\n", * (double*) px, * (double*) (px + 8)); | |
71 | + free((void*) px); | |
72 | +} | |
73 | + | |
74 | + | |
75 | +int main() { | |
76 | + test1(); | |
77 | + test2(); | |
78 | + test3(); | |
79 | + test4(); | |
80 | + test5(); | |
81 | + test6(); | |
82 | + test7(); | |
83 | + test8(); | |
84 | + return 0; | |
85 | +} |
@@ -77,7 +77,14 @@ def firstDifference(a, b): | ||
77 | 77 | return i |
78 | 78 | return commonLen |
79 | 79 | |
80 | -def compareSet(a1,a2,b1,b2): | |
80 | +# a1 and a2 are the expected stdout and stderr. | |
81 | +# b1 and b2 are the actual stdout and stderr. | |
82 | +# Compare the two, sets. Allow any individual line | |
83 | +# to appear in either stdout or stderr. This is because | |
84 | +# the way we obtain output on the ARM combines both | |
85 | +# streams into one sequence. | |
86 | + | |
87 | +def compareOuput(a1,a2,b1,b2): | |
81 | 88 | while True: |
82 | 89 | totalLen = len(a1) + len(a2) + len(b1) + len(b2) |
83 | 90 | a1, b1 = matchCommon(a1, b1) |
@@ -96,6 +103,8 @@ def compareSet(a1,a2,b1,b2): | ||
96 | 103 | return False |
97 | 104 | |
98 | 105 | def matchCommon(a, b): |
106 | + """Remove common items from the beginning of a and b, | |
107 | + return just the tails that are different.""" | |
99 | 108 | while len(a) > 0 and len(b) > 0 and a[0] == b[0]: |
100 | 109 | a = a[1:] |
101 | 110 | b = b[1:] |
@@ -105,25 +114,20 @@ def rewritePaths(args): | ||
105 | 114 | return [rewritePath(x) for x in args] |
106 | 115 | |
107 | 116 | def rewritePath(p): |
117 | + """Take a path that's correct on the x86 and convert to a path | |
118 | + that's correct on ARM.""" | |
108 | 119 | if p.startswith("data/"): |
109 | 120 | p = "/system/bin/accdata/" + p |
110 | 121 | return p |
111 | 122 | |
112 | 123 | class TestACC(unittest.TestCase): |
113 | - | |
114 | - def compileCheckOld(self, args, stdErrResult, stdOutResult=""): | |
115 | - out, err = compile(args) | |
116 | - compare(out, stdOutResult) | |
117 | - compare(err, stdErrResult) | |
118 | - self.assertEqual(out, stdOutResult) | |
119 | - self.assertEqual(err, stdErrResult) | |
120 | 124 | |
121 | 125 | def checkResult(self, out, err, stdErrResult, stdOutResult=""): |
122 | 126 | a1 = out.splitlines() |
123 | 127 | a2 = err.splitlines() |
124 | 128 | b2 = stdErrResult.splitlines() |
125 | 129 | b1 = stdOutResult.splitlines() |
126 | - self.assertEqual(True, compareSet(a1,a2,b1,b2)) | |
130 | + self.assertEqual(True, compareOuput(a1,a2,b1,b2)) | |
127 | 131 | |
128 | 132 | def compileCheck(self, args, stdErrResult, stdOutResult="", |
129 | 133 | targets=['arm', 'x86']): |
@@ -174,65 +178,77 @@ class TestACC(unittest.TestCase): | ||
174 | 178 | |
175 | 179 | def testRunFlops(self): |
176 | 180 | self.compileCheck(["-R", "data/flops.c"], |
177 | - "Executing compiled code:\nresult: 0\n", | |
178 | - "-1.1 = -1.1\n" + | |
179 | - "!1.2 = 0\n" + | |
180 | - "!0 = 1\n" + | |
181 | - "double op double:\n" + | |
182 | - "1 + 2 = 3\n" + | |
183 | - "1 - 2 = -1\n" + | |
184 | - "1 * 2 = 2\n" + | |
185 | - "1 / 2 = 0.5\n" + | |
186 | - "float op float:\n" + | |
187 | - "1 + 2 = 3\n" + | |
188 | - "1 - 2 = -1\n" + | |
189 | - "1 * 2 = 2\n" + | |
190 | - "1 / 2 = 0.5\n" + | |
191 | - "double op float:\n" + | |
192 | - "1 + 2 = 3\n" + | |
193 | - "1 - 2 = -1\n" + | |
194 | - "1 * 2 = 2\n" + | |
195 | - "1 / 2 = 0.5\n" + | |
196 | - "double op int:\n" + | |
197 | - "1 + 2 = 3\n" + | |
198 | - "1 - 2 = -1\n" + | |
199 | - "1 * 2 = 2\n" + | |
200 | - "1 / 2 = 0.5\n" + | |
201 | - "int op double:\n" + | |
202 | - "1 + 2 = 3\n" + | |
203 | - "1 - 2 = -1\n" + | |
204 | - "1 * 2 = 2\n" + | |
205 | - "1 / 2 = 0.5\n" + | |
206 | - "double op double:\n" + | |
207 | - "1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" + | |
208 | - "1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" + | |
209 | - "2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" + | |
210 | - "double op float:\n" + | |
211 | - "1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" + | |
212 | - "1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" + | |
213 | - "2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" + | |
214 | - "float op float:\n" + | |
215 | - "1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" + | |
216 | - "1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" + | |
217 | - "2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" + | |
218 | - "int op double:\n" + | |
219 | - "1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" + | |
220 | - "1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" + | |
221 | - "2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" + | |
222 | - "double op int:\n" + | |
223 | - "1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" + | |
224 | - "1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" + | |
225 | - "2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" + | |
226 | - "branching: 1 0 1\n" + | |
227 | - "testpassi: 1 2 3 4 5 6 7 8\n" + | |
228 | - "testpassf: 1 2 3 4 5 6 7 8\n" + | |
229 | - "testpassd: 1 2 3 4 5 6 7 8\n" + | |
230 | - "testpassidf: 1 2 3\n" | |
231 | - ) | |
232 | - | |
233 | - def oldtestArmRunReturnVal(self): | |
234 | - self.compileCheckArm(["-R", "/system/bin/accdata/data/returnval-ansi.c"], | |
235 | - "Executing compiled code:\nresult: 42\n") | |
181 | + """Executing compiled code: | |
182 | +result: 0""", | |
183 | +"""-1.1 = -1.1 | |
184 | +!1.2 = 0 | |
185 | +!0 = 1 | |
186 | +double op double: | |
187 | +1 + 2 = 3 | |
188 | +1 - 2 = -1 | |
189 | +1 * 2 = 2 | |
190 | +1 / 2 = 0.5 | |
191 | +float op float: | |
192 | +1 + 2 = 3 | |
193 | +1 - 2 = -1 | |
194 | +1 * 2 = 2 | |
195 | +1 / 2 = 0.5 | |
196 | +double op float: | |
197 | +1 + 2 = 3 | |
198 | +1 - 2 = -1 | |
199 | +1 * 2 = 2 | |
200 | +1 / 2 = 0.5 | |
201 | +double op int: | |
202 | +1 + 2 = 3 | |
203 | +1 - 2 = -1 | |
204 | +1 * 2 = 2 | |
205 | +1 / 2 = 0.5 | |
206 | +int op double: | |
207 | +1 + 2 = 3 | |
208 | +1 - 2 = -1 | |
209 | +1 * 2 = 2 | |
210 | +1 / 2 = 0.5 | |
211 | +double op double: | |
212 | +1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 | |
213 | +1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 | |
214 | +2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 | |
215 | +double op float: | |
216 | +1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 | |
217 | +1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 | |
218 | +2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 | |
219 | +float op float: | |
220 | +1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 | |
221 | +1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 | |
222 | +2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 | |
223 | +int op double: | |
224 | +1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 | |
225 | +1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 | |
226 | +2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 | |
227 | +double op int: | |
228 | +1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 | |
229 | +1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 | |
230 | +2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 | |
231 | +branching: 1 0 1 | |
232 | +testpassi: 1 2 3 4 5 6 7 8 | |
233 | +testpassf: 1 2 3 4 5 6 7 8 | |
234 | +testpassd: 1 2 3 4 5 6 7 8 | |
235 | +testpassidf: 1 2 3 | |
236 | +""") | |
237 | + def testCasts(self): | |
238 | + self.compileCheck(["-R", "data/casts.c"], | |
239 | + """Executing compiled code: | |
240 | +result: 0""", """Reading from a pointer: 3 3 | |
241 | +Writing to a pointer: 4 | |
242 | +Testing casts: 3 3 4.5 4 | |
243 | +Testing reading (int*): 4 | |
244 | +Testing writing (int*): 8 9 | |
245 | +Testing reading (char*): 0x78 0x56 0x34 0x12 | |
246 | +Testing writing (char*): 0x87654321 | |
247 | +f(10) | |
248 | +Function pointer result: 70 | |
249 | +Testing read/write (float*): 8.8 9.9 | |
250 | +Testing read/write (double*): 8.8 9.9 | |
251 | +""") | |
236 | 252 | |
237 | 253 | if __name__ == '__main__': |
238 | 254 | if not outputCanRun(): |