system/corennnnn
リビジョン | 304176c90984efc0bda9d01ad07ea0c92af822bb (tree) |
---|---|
日時 | 2009-08-05 06:56:12 |
作者 | Android (Google) Code Review <android-gerrit@goog...> |
コミッター | Android (Google) Code Review |
Merge change 20014
* changes:
@@ -139,16 +139,17 @@ class Compiler : public ErrorSink { | ||
139 | 139 | TY_VOID, // 3 |
140 | 140 | TY_FLOAT, // 4 |
141 | 141 | TY_DOUBLE, // 5 |
142 | - TY_POINTER, // 6 | |
143 | - TY_ARRAY, // 7 | |
144 | - TY_STRUCT, // 8 | |
145 | - TY_FUNC, // 9 | |
146 | - TY_PARAM // 10 | |
142 | + TY_POINTER, // 6 | |
143 | + TY_ARRAY, // 7 | |
144 | + TY_STRUCT, // 8 | |
145 | + TY_FUNC, // 9 | |
146 | + TY_PARAM // 10 | |
147 | 147 | }; |
148 | 148 | |
149 | 149 | struct Type { |
150 | 150 | TypeTag tag; |
151 | - tokenid_t id; // For function arguments (stores length for array) | |
151 | + tokenid_t id; // For function arguments, local vars | |
152 | + int length; // length of array | |
152 | 153 | Type* pHead; |
153 | 154 | Type* pTail; |
154 | 155 | }; |
@@ -405,7 +406,16 @@ class Compiler : public ErrorSink { | ||
405 | 406 | /** |
406 | 407 | * Convert R0 to the given type. |
407 | 408 | */ |
408 | - virtual void convertR0(Type* pType) = 0; | |
409 | + | |
410 | + void convertR0(Type* pType) { | |
411 | + convertR0Imp(pType, false); | |
412 | + } | |
413 | + | |
414 | + void castR0(Type* pType) { | |
415 | + convertR0Imp(pType, true); | |
416 | + } | |
417 | + | |
418 | + virtual void convertR0Imp(Type* pType, bool isCast) = 0; | |
409 | 419 | |
410 | 420 | /* Emit code to adjust the stack for a function call. Return the |
411 | 421 | * label for the address of the instruction that adjusts the |
@@ -622,14 +632,40 @@ class Compiler : public ErrorSink { | ||
622 | 632 | return collapseType(getR0Type()->tag); |
623 | 633 | } |
624 | 634 | |
625 | - bool isFloatType(Type* pType) { | |
635 | + static bool isFloatType(Type* pType) { | |
626 | 636 | return isFloatTag(pType->tag); |
627 | 637 | } |
628 | 638 | |
629 | - bool isFloatTag(TypeTag tag) { | |
639 | + static bool isFloatTag(TypeTag tag) { | |
630 | 640 | return tag == TY_FLOAT || tag == TY_DOUBLE; |
631 | 641 | } |
632 | 642 | |
643 | + static bool isPointerType(Type* pType) { | |
644 | + return isPointerTag(pType->tag); | |
645 | + } | |
646 | + | |
647 | + static bool isPointerTag(TypeTag tag) { | |
648 | + return tag == TY_POINTER || tag == TY_ARRAY; | |
649 | + } | |
650 | + | |
651 | + Type* getPointerArithmeticResultType(Type* a, Type* b) { | |
652 | + TypeTag aTag = a->tag; | |
653 | + TypeTag bTag = b->tag; | |
654 | + if (aTag == TY_POINTER) { | |
655 | + return a; | |
656 | + } | |
657 | + if (bTag == TY_POINTER) { | |
658 | + return b; | |
659 | + } | |
660 | + if (aTag == TY_ARRAY) { | |
661 | + return a->pTail; | |
662 | + } | |
663 | + if (bTag == TY_ARRAY) { | |
664 | + return b->pTail; | |
665 | + } | |
666 | + return NULL; | |
667 | + } | |
668 | + | |
633 | 669 | Type* mkpInt; |
634 | 670 | |
635 | 671 | private: |
@@ -848,8 +884,8 @@ class Compiler : public ErrorSink { | ||
848 | 884 | bool isFloatTOS = isFloatTag(tagTOS); |
849 | 885 | if (!isFloatR0 && !isFloatTOS) { |
850 | 886 | setupIntPtrArgs(); |
851 | - bool isPtrR0 = tagR0 == TY_POINTER; | |
852 | - bool isPtrTOS = tagTOS == TY_POINTER; | |
887 | + bool isPtrR0 = isPointerTag(tagR0); | |
888 | + bool isPtrTOS = isPointerTag(tagTOS); | |
853 | 889 | if (isPtrR0 || isPtrTOS) { |
854 | 890 | if (isPtrR0 && isPtrTOS) { |
855 | 891 | if (op != OP_MINUS) { |
@@ -871,7 +907,8 @@ class Compiler : public ErrorSink { | ||
871 | 907 | if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) { |
872 | 908 | error("Unsupported pointer-scalar operation %d", op); |
873 | 909 | } |
874 | - Type* pPtrType = isPtrR0 ? pR0Type : pTOSType; | |
910 | + Type* pPtrType = getPointerArithmeticResultType( | |
911 | + pR0Type, pTOSType); | |
875 | 912 | int size = sizeOf(pPtrType->pHead); |
876 | 913 | if (size != 1) { |
877 | 914 | // TODO: Optimize for power-of-two. |
@@ -1131,7 +1168,8 @@ class Compiler : public ErrorSink { | ||
1131 | 1168 | virtual void loadR0FromR0() { |
1132 | 1169 | Type* pPointerType = getR0Type(); |
1133 | 1170 | assert(pPointerType->tag == TY_POINTER); |
1134 | - switch (pPointerType->pHead->tag) { | |
1171 | + TypeTag tag = pPointerType->pHead->tag; | |
1172 | + switch (tag) { | |
1135 | 1173 | case TY_POINTER: |
1136 | 1174 | case TY_INT: |
1137 | 1175 | case TY_FLOAT: |
@@ -1147,7 +1185,7 @@ class Compiler : public ErrorSink { | ||
1147 | 1185 | o4(0xE1C000D0); // ldrd r0, [r0] |
1148 | 1186 | break; |
1149 | 1187 | default: |
1150 | - error("loadR0FromR0: unimplemented type"); | |
1188 | + error("loadR0FromR0: unimplemented type %d", tag); | |
1151 | 1189 | break; |
1152 | 1190 | } |
1153 | 1191 | setR0Type(pPointerType->pHead); |
@@ -1197,9 +1235,27 @@ class Compiler : public ErrorSink { | ||
1197 | 1235 | return result; |
1198 | 1236 | } |
1199 | 1237 | |
1200 | - virtual void convertR0(Type* pType){ | |
1238 | + virtual void convertR0Imp(Type* pType, bool isCast){ | |
1201 | 1239 | Type* pR0Type = getR0Type(); |
1202 | - if (bitsSame(pType, pR0Type)) { | |
1240 | + if (isPointerType(pType) && isPointerType(pR0Type)) { | |
1241 | + Type* pA = pR0Type; | |
1242 | + Type* pB = pType; | |
1243 | + // Array decays to pointer | |
1244 | + if (pA->tag == TY_ARRAY && pB->tag == TY_POINTER) { | |
1245 | + pA = pA->pTail; | |
1246 | + } | |
1247 | + if (typeEqual(pA, pB)) { | |
1248 | + return; // OK | |
1249 | + } | |
1250 | + if (pB->pHead->tag == TY_VOID) { | |
1251 | + return; // convert to void* is OK. | |
1252 | + } | |
1253 | + if (pA->tag == TY_POINTER && pB->tag == TY_POINTER | |
1254 | + && isCast) { | |
1255 | + return; // OK | |
1256 | + } | |
1257 | + error("Incompatible pointer or array types"); | |
1258 | + } else if (bitsSame(pType, pR0Type)) { | |
1203 | 1259 | // do nothing special |
1204 | 1260 | } else { |
1205 | 1261 | TypeTag r0Tag = collapseType(pR0Type->tag); |
@@ -1423,14 +1479,17 @@ class Compiler : public ErrorSink { | ||
1423 | 1479 | return 2; |
1424 | 1480 | case TY_CHAR: |
1425 | 1481 | return 1; |
1426 | - default: | |
1427 | - return 0; | |
1428 | 1482 | case TY_FLOAT: |
1429 | 1483 | return 4; |
1430 | 1484 | case TY_DOUBLE: |
1431 | 1485 | return 8; |
1432 | 1486 | case TY_POINTER: |
1433 | 1487 | return 4; |
1488 | + case TY_ARRAY: | |
1489 | + return pType->length * sizeOf(pType->pHead); | |
1490 | + default: | |
1491 | + error("Unsupported type %d", pType->tag); | |
1492 | + return 0; | |
1434 | 1493 | } |
1435 | 1494 | } |
1436 | 1495 |
@@ -1438,6 +1497,8 @@ class Compiler : public ErrorSink { | ||
1438 | 1497 | switch(pType->tag) { |
1439 | 1498 | case TY_DOUBLE: |
1440 | 1499 | return 8; |
1500 | + case TY_ARRAY: | |
1501 | + return stackAlignmentOf(pType->pHead); | |
1441 | 1502 | default: |
1442 | 1503 | return 4; |
1443 | 1504 | } |
@@ -1447,6 +1508,11 @@ class Compiler : public ErrorSink { | ||
1447 | 1508 | switch(pType->tag) { |
1448 | 1509 | case TY_DOUBLE: |
1449 | 1510 | return 8; |
1511 | + case TY_ARRAY: | |
1512 | + return sizeOf(pType); | |
1513 | + case TY_FUNC: | |
1514 | + error("stackSizeOf func not supported"); | |
1515 | + return 4; | |
1450 | 1516 | default: |
1451 | 1517 | return 4; |
1452 | 1518 | } |
@@ -1911,8 +1977,8 @@ class Compiler : public ErrorSink { | ||
1911 | 1977 | bool isFloatR0 = isFloatTag(tagR0); |
1912 | 1978 | bool isFloatTOS = isFloatTag(tagTOS); |
1913 | 1979 | if (!isFloatR0 && !isFloatTOS) { |
1914 | - bool isPtrR0 = tagR0 == TY_POINTER; | |
1915 | - bool isPtrTOS = tagTOS == TY_POINTER; | |
1980 | + bool isPtrR0 = isPointerTag(tagR0); | |
1981 | + bool isPtrTOS = isPointerTag(tagTOS); | |
1916 | 1982 | if (isPtrR0 || isPtrTOS) { |
1917 | 1983 | if (isPtrR0 && isPtrTOS) { |
1918 | 1984 | if (op != OP_MINUS) { |
@@ -1936,7 +2002,8 @@ class Compiler : public ErrorSink { | ||
1936 | 2002 | if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) { |
1937 | 2003 | error("Unsupported pointer-scalar operation %d", op); |
1938 | 2004 | } |
1939 | - Type* pPtrType = isPtrR0 ? pR0Type : pTOSType; | |
2005 | + Type* pPtrType = getPointerArithmeticResultType( | |
2006 | + pR0Type, pTOSType); | |
1940 | 2007 | o(0x59); /* pop %ecx */ |
1941 | 2008 | int size = sizeOf(pPtrType->pHead); |
1942 | 2009 | if (size != 1) { |
@@ -2146,7 +2213,8 @@ class Compiler : public ErrorSink { | ||
2146 | 2213 | virtual void loadR0FromR0() { |
2147 | 2214 | Type* pPointerType = getR0Type(); |
2148 | 2215 | assert(pPointerType->tag == TY_POINTER); |
2149 | - switch (pPointerType->pHead->tag) { | |
2216 | + TypeTag tag = pPointerType->pHead->tag; | |
2217 | + switch (tag) { | |
2150 | 2218 | case TY_POINTER: |
2151 | 2219 | case TY_INT: |
2152 | 2220 | o2(0x008b); /* mov (%eax), %eax */ |
@@ -2166,7 +2234,7 @@ class Compiler : public ErrorSink { | ||
2166 | 2234 | o2(0x00dd); // fldl (%eax) |
2167 | 2235 | break; |
2168 | 2236 | default: |
2169 | - error("loadR0FromR0: unsupported type"); | |
2237 | + error("loadR0FromR0: unsupported type %d", tag); | |
2170 | 2238 | break; |
2171 | 2239 | } |
2172 | 2240 | setR0Type(pPointerType->pHead); |
@@ -2183,14 +2251,32 @@ class Compiler : public ErrorSink { | ||
2183 | 2251 | return getPC() - 4; |
2184 | 2252 | } |
2185 | 2253 | |
2186 | - virtual void convertR0(Type* pType){ | |
2254 | + virtual void convertR0Imp(Type* pType, bool isCast){ | |
2187 | 2255 | Type* pR0Type = getR0Type(); |
2188 | 2256 | if (pR0Type == NULL) { |
2189 | 2257 | assert(false); |
2190 | 2258 | setR0Type(pType); |
2191 | 2259 | return; |
2192 | 2260 | } |
2193 | - if (bitsSame(pType, pR0Type)) { | |
2261 | + if (isPointerType(pType) && isPointerType(pR0Type)) { | |
2262 | + Type* pA = pR0Type; | |
2263 | + Type* pB = pType; | |
2264 | + // Array decays to pointer | |
2265 | + if (pA->tag == TY_ARRAY && pB->tag == TY_POINTER) { | |
2266 | + pA = pA->pTail; | |
2267 | + } | |
2268 | + if (typeEqual(pA, pB)) { | |
2269 | + return; // OK | |
2270 | + } | |
2271 | + if (pB->pHead->tag == TY_VOID) { | |
2272 | + return; // convert to void* is OK. | |
2273 | + } | |
2274 | + if (pA->tag == TY_POINTER && pB->tag == TY_POINTER | |
2275 | + && isCast) { | |
2276 | + return; // OK | |
2277 | + } | |
2278 | + error("Incompatible pointer or array types"); | |
2279 | + } else if (bitsSame(pType, pR0Type)) { | |
2194 | 2280 | // do nothing special |
2195 | 2281 | } else if (isFloatType(pType) && isFloatType(pR0Type)) { |
2196 | 2282 | // do nothing special, both held in same register on x87. |
@@ -2326,6 +2412,11 @@ class Compiler : public ErrorSink { | ||
2326 | 2412 | return 1; |
2327 | 2413 | case TY_SHORT: |
2328 | 2414 | return 2; |
2415 | + case TY_ARRAY: | |
2416 | + return alignmentOf(pType->pHead); | |
2417 | + case TY_FUNC: | |
2418 | + error("alignment of func not supported"); | |
2419 | + return 1; | |
2329 | 2420 | default: |
2330 | 2421 | return 4; |
2331 | 2422 | } |
@@ -2342,14 +2433,17 @@ class Compiler : public ErrorSink { | ||
2342 | 2433 | return 2; |
2343 | 2434 | case TY_CHAR: |
2344 | 2435 | return 1; |
2345 | - default: | |
2346 | - return 0; | |
2347 | 2436 | case TY_FLOAT: |
2348 | 2437 | return 4; |
2349 | 2438 | case TY_DOUBLE: |
2350 | 2439 | return 8; |
2351 | 2440 | case TY_POINTER: |
2352 | 2441 | return 4; |
2442 | + case TY_ARRAY: | |
2443 | + return pType->length * sizeOf(pType->pHead); | |
2444 | + default: | |
2445 | + error("Unsupported type %d", pType->tag); | |
2446 | + return 0; | |
2353 | 2447 | } |
2354 | 2448 | } |
2355 | 2449 |
@@ -2361,6 +2455,11 @@ class Compiler : public ErrorSink { | ||
2361 | 2455 | switch(pType->tag) { |
2362 | 2456 | case TY_DOUBLE: |
2363 | 2457 | return 8; |
2458 | + case TY_ARRAY: | |
2459 | + return sizeOf(pType); | |
2460 | + case TY_FUNC: | |
2461 | + error("stackSizeOf func not supported"); | |
2462 | + return 4; | |
2364 | 2463 | default: |
2365 | 2464 | return 4; |
2366 | 2465 | } |
@@ -3911,7 +4010,7 @@ class Compiler : public ErrorSink { | ||
3911 | 4010 | skip(')'); |
3912 | 4011 | unary(); |
3913 | 4012 | pGen->forceR0RVal(); |
3914 | - pGen->convertR0(pCast); | |
4013 | + pGen->castR0(pCast); | |
3915 | 4014 | } else { |
3916 | 4015 | commaExpr(); |
3917 | 4016 | skip(')'); |
@@ -3959,10 +4058,18 @@ class Compiler : public ErrorSink { | ||
3959 | 4058 | } |
3960 | 4059 | } |
3961 | 4060 | // load a variable |
3962 | - Type* pVal = createPtrType(pVI->pType); | |
4061 | + Type* pVal; | |
4062 | + ExpressionType et; | |
4063 | + if (pVI->pType->tag == TY_ARRAY) { | |
4064 | + pVal = pVI->pType; | |
4065 | + et = ET_RVALUE; | |
4066 | + } else { | |
4067 | + pVal = createPtrType(pVI->pType); | |
4068 | + et = ET_LVALUE; | |
4069 | + } | |
3963 | 4070 | if (n) { |
3964 | - ExpressionType et = ET_LVALUE; | |
3965 | - if (pVal->pHead->tag == TY_FUNC) { | |
4071 | + int tag = pVal->pHead->tag; | |
4072 | + if (tag == TY_FUNC) { | |
3966 | 4073 | et = ET_RVALUE; |
3967 | 4074 | } |
3968 | 4075 | pGen->leaR0(n, pVal, et); |
@@ -4251,6 +4358,8 @@ class Compiler : public ErrorSink { | ||
4251 | 4358 | } |
4252 | 4359 | if (at == TY_POINTER) { |
4253 | 4360 | return typeEqual(a->pHead, b->pHead); |
4361 | + } else if (at == TY_ARRAY) { | |
4362 | + return a->length == b->length && typeEqual(a->pHead, b->pHead); | |
4254 | 4363 | } else if (at == TY_FUNC || at == TY_PARAM) { |
4255 | 4364 | return typeEqual(a->pHead, b->pHead) |
4256 | 4365 | && typeEqual(a->pTail, b->pTail); |
@@ -4345,6 +4454,9 @@ class Compiler : public ErrorSink { | ||
4345 | 4454 | } |
4346 | 4455 | buffer.append('*'); |
4347 | 4456 | break; |
4457 | + case TY_ARRAY: | |
4458 | + decodeTypeImpPrefix(buffer, pType->pHead); | |
4459 | + break; | |
4348 | 4460 | case TY_FUNC: |
4349 | 4461 | decodeTypeImp(buffer, pType->pHead); |
4350 | 4462 | break; |
@@ -4369,6 +4481,13 @@ class Compiler : public ErrorSink { | ||
4369 | 4481 | } |
4370 | 4482 | decodeTypeImpPostfix(buffer, pType->pHead); |
4371 | 4483 | break; |
4484 | + case TY_ARRAY: | |
4485 | + { | |
4486 | + String temp; | |
4487 | + temp.printf("[%d]", pType->length); | |
4488 | + buffer.append(temp); | |
4489 | + } | |
4490 | + break; | |
4372 | 4491 | case TY_FUNC: |
4373 | 4492 | buffer.append('('); |
4374 | 4493 | for(Type* pArg = pType->pTail; pArg; pArg = pArg->pTail) { |
@@ -4418,9 +4537,13 @@ class Compiler : public ErrorSink { | ||
4418 | 4537 | nameRequired, reportFailure); |
4419 | 4538 | if (declName) { |
4420 | 4539 | // Clone the parent type so we can set a unique ID |
4540 | + Type* pOldType = pType; | |
4421 | 4541 | pType = createType(pType->tag, pType->pHead, pType->pTail); |
4422 | 4542 | |
4423 | 4543 | pType->id = declName; |
4544 | + pType->length = pOldType->length; | |
4545 | + } else if (nameRequired) { | |
4546 | + error("Expected a variable name"); | |
4424 | 4547 | } |
4425 | 4548 | // fprintf(stderr, "Parsed a declaration: "); |
4426 | 4549 | // printType(pType); |
@@ -4490,11 +4613,27 @@ class Compiler : public ErrorSink { | ||
4490 | 4613 | error("Expected name. Got %s", temp.getUnwrapped()); |
4491 | 4614 | reportFailure = true; |
4492 | 4615 | } |
4493 | - while (accept('(')) { | |
4494 | - // Function declaration | |
4495 | - Type* pTail = acceptArgs(nameAllowed); | |
4496 | - pType = createType(TY_FUNC, pType, pTail); | |
4497 | - skip(')'); | |
4616 | + for(;;) { | |
4617 | + if (accept('(')) { | |
4618 | + // Function declaration | |
4619 | + Type* pTail = acceptArgs(nameAllowed); | |
4620 | + pType = createType(TY_FUNC, pType, pTail); | |
4621 | + skip(')'); | |
4622 | + } if (accept('[')) { | |
4623 | + if (tok != ']') { | |
4624 | + if (tok != TOK_NUM || tokc <= 0) { | |
4625 | + error("Expected positive integer constant"); | |
4626 | + } else { | |
4627 | + Type* pDecayType = createPtrType(pType); | |
4628 | + pType = createType(TY_ARRAY, pType, pDecayType); | |
4629 | + pType->length = tokc; | |
4630 | + } | |
4631 | + next(); | |
4632 | + } | |
4633 | + skip(']'); | |
4634 | + } else { | |
4635 | + break; | |
4636 | + } | |
4498 | 4637 | } |
4499 | 4638 | |
4500 | 4639 | if (pNewHead) { |
@@ -0,0 +1,77 @@ | ||
1 | +// Array allocation tests | |
2 | + | |
3 | +void testLocalInt() | |
4 | +{ | |
5 | + int a[3]; | |
6 | + a[0] = 1; | |
7 | + a[1] = 2; | |
8 | + a[2] = a[0] + a[1]; | |
9 | + printf("localInt: %d\n", a[2]); | |
10 | +} | |
11 | + | |
12 | +char a[3]; | |
13 | +double d[3]; | |
14 | + | |
15 | +void testGlobalChar() | |
16 | +{ | |
17 | + a[0] = 1; | |
18 | + a[1] = 2; | |
19 | + a[2] = a[0] + a[1]; | |
20 | + printf("globalChar: %d\n", a[2]); | |
21 | +} | |
22 | + | |
23 | +void testGlobalDouble() | |
24 | +{ | |
25 | + d[0] = 1; | |
26 | + d[1] = 2; | |
27 | + d[2] = d[0] + d[1]; | |
28 | + printf("globalDouble: %g\n", d[2]); | |
29 | +} | |
30 | + | |
31 | +void testLocalDouble() | |
32 | +{ | |
33 | + double d[3]; | |
34 | + float m[12]; | |
35 | + m[0] = 1.0f; | |
36 | + m[1] = 2.0f; | |
37 | + d[0] = 1.0; | |
38 | + d[1] = 2.0; | |
39 | + d[2] = d[0] + d[1]; | |
40 | + m[2] = m[0] + m[1]; | |
41 | + printf("localDouble: %g %g\n", d[2], m[2]); | |
42 | +} | |
43 | + | |
44 | +void vectorAdd(int* a, int* b, float* c, int len) { | |
45 | + int i; | |
46 | + for(i = 0; i < len; i++) { | |
47 | + c[i] = a[i] + b[i]; | |
48 | + } | |
49 | +} | |
50 | + | |
51 | +void testArgs() { | |
52 | + int a[3], b[3]; | |
53 | + float c[3]; | |
54 | + int i; | |
55 | + int len = 3; | |
56 | + for(i = 0; i < len; i++) { | |
57 | + a[i] = i; | |
58 | + b[i] = i; | |
59 | + c[i] = 0; | |
60 | + } | |
61 | + vectorAdd(a,b,c, len); | |
62 | + printf("testArgs:"); | |
63 | + for(i = 0; i < len; i++) { | |
64 | + printf(" %g", c[i]); | |
65 | + } | |
66 | + printf("\n"); | |
67 | +} | |
68 | + | |
69 | +int main() | |
70 | +{ | |
71 | + testLocalInt(); | |
72 | + testLocalDouble(); | |
73 | + testGlobalChar(); | |
74 | + testGlobalDouble(); | |
75 | + testArgs(); | |
76 | + return 0; | |
77 | +} |
@@ -387,6 +387,16 @@ result: 0 | ||
387 | 387 | result: -2 |
388 | 388 | ""","""""") |
389 | 389 | |
390 | + def testArray(self): | |
391 | + self.compileCheck(["-R", "data/array.c"], """Executing compiled code: | |
392 | +localInt: 3 | |
393 | +localDouble: 3 3 | |
394 | +globalChar: 3 | |
395 | +globalDouble: 3 | |
396 | +testArgs: 0 2 4 | |
397 | +result: 0 | |
398 | +""","""""") | |
399 | + | |
390 | 400 | if __name__ == '__main__': |
391 | 401 | if not outputCanRun(): |
392 | 402 | print "Many tests are expected to fail, because acc is not a 32-bit x86 Linux executable." |