Merge change 7048
* changes: Implement general casts and pointer dereferencing.
This commit is contained in:
commit
13ac7f6cee
|
@ -1019,6 +1019,7 @@ class Compiler : public ErrorSink {
|
|||
LOG_API("storeR0(%d);\n", ea);
|
||||
TypeTag tag = pType->tag;
|
||||
switch (tag) {
|
||||
case TY_POINTER:
|
||||
case TY_INT:
|
||||
case TY_FLOAT:
|
||||
if (ea > -LOCAL && ea < LOCAL) {
|
||||
|
@ -2027,6 +2028,7 @@ class Compiler : public ErrorSink {
|
|||
TypeTag tag = pType->tag;
|
||||
switch (tag) {
|
||||
case TY_INT:
|
||||
case TY_POINTER:
|
||||
gmov(6, ea); /* mov %eax, EA */
|
||||
break;
|
||||
case TY_FLOAT:
|
||||
|
@ -3663,41 +3665,34 @@ class Compiler : public ErrorSink {
|
|||
pGen->genUnaryOp(a);
|
||||
}
|
||||
} else if (t == '(') {
|
||||
expr();
|
||||
skip(')');
|
||||
} else if (t == '*') {
|
||||
/* This is a pointer dereference, but we currently only
|
||||
* support a pointer dereference if it's immediately
|
||||
* in front of a cast. So parse the cast right here.
|
||||
*/
|
||||
skip('(');
|
||||
Type* pCast = expectCastTypeDeclaration(mLocalArena);
|
||||
// We currently only handle 3 types of cast:
|
||||
// (int*), (char*) , (int (*)())
|
||||
if(typeEqual(pCast, mkpIntPtr)) {
|
||||
t = TOK_INT;
|
||||
} else if (typeEqual(pCast, mkpCharPtr)) {
|
||||
t = TOK_CHAR;
|
||||
} else if (typeEqual(pCast, mkpFloatPtr)) {
|
||||
t = TOK_FLOAT;
|
||||
} else if (typeEqual(pCast, mkpDoublePtr)) {
|
||||
t = TOK_DOUBLE;
|
||||
} else if (typeEqual(pCast, mkpPtrIntFn)){
|
||||
t = 0;
|
||||
// It's either a cast or an expression
|
||||
Type* pCast = acceptCastTypeDeclaration(mLocalArena);
|
||||
if (pCast) {
|
||||
skip(')');
|
||||
unary(false);
|
||||
pGen->convertR0(pCast);
|
||||
} else {
|
||||
String buffer;
|
||||
decodeType(buffer, pCast);
|
||||
error("Unsupported cast type %s", buffer.getUnwrapped());
|
||||
decodeType(buffer, mkpPtrIntFn);
|
||||
}
|
||||
skip(')');
|
||||
unary(false);
|
||||
if (accept('=')) {
|
||||
pGen->pushR0();
|
||||
expr();
|
||||
pGen->storeR0ToTOS(pCast);
|
||||
} else if (t) {
|
||||
pGen->loadR0FromR0(pCast);
|
||||
skip(')');
|
||||
}
|
||||
} else if (t == '*') {
|
||||
/* This is a pointer dereference.
|
||||
*/
|
||||
unary(false);
|
||||
Type* pR0Type = pGen->getR0Type();
|
||||
if (pR0Type->tag != TY_POINTER) {
|
||||
error("Expected a pointer type.");
|
||||
} else {
|
||||
if (pR0Type->pHead->tag == TY_FUNC) {
|
||||
t = 0;
|
||||
}
|
||||
if (accept('=')) {
|
||||
pGen->pushR0();
|
||||
expr();
|
||||
pGen->storeR0ToTOS(pR0Type);
|
||||
} else if (t) {
|
||||
pGen->loadR0FromR0(pR0Type);
|
||||
}
|
||||
}
|
||||
// Else we fall through to the function call below, with
|
||||
// t == 0 to trigger an indirect function call. Hack!
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
void test1() {
|
||||
int a = 3;
|
||||
int* pb = &a;
|
||||
int c = *pb;
|
||||
printf("Reading from a pointer: %d %d\n", a, c);
|
||||
*pb = 4;
|
||||
printf("Writing to a pointer: %d\n", a);
|
||||
printf("Testing casts: %d %g %g %d\n", 3, (float) 3, 4.5, (int) 4.5);
|
||||
}
|
||||
|
||||
void test2() {
|
||||
int x = 4;
|
||||
int px = &x;
|
||||
// int z = * px; // An error, expected a pointer type
|
||||
int y = * (int*) px;
|
||||
printf("Testing reading (int*): %d\n", y);
|
||||
}
|
||||
|
||||
void test3() {
|
||||
int px = (int) malloc(120);
|
||||
* (int*) px = 8;
|
||||
* (int*) (px + 4) = 9;
|
||||
printf("Testing writing (int*): %d %d\n", * (int*) px, * (int*) (px + 4));
|
||||
free((void*) px);
|
||||
}
|
||||
|
||||
void test4() {
|
||||
int x = 0x12345678;
|
||||
int px = &x;
|
||||
int a = * (char*) px;
|
||||
int b = * (char*) (px + 1);
|
||||
int c = * (char*) (px + 2);
|
||||
int d = * (char*) (px + 3);
|
||||
printf("Testing reading (char*): 0x%02x 0x%02x 0x%02x 0x%02x\n", a, b, c, d);
|
||||
}
|
||||
|
||||
void test5() {
|
||||
int x = 0xFFFFFFFF;
|
||||
int px = &x;
|
||||
* (char*) px = 0x21;
|
||||
* (char*) (px + 1) = 0x43;
|
||||
* (char*) (px + 2) = 0x65;
|
||||
* (char*) (px + 3) = 0x87;
|
||||
printf("Testing writing (char*): 0x%08x\n", x);
|
||||
}
|
||||
|
||||
int f(int b) {
|
||||
printf("f(%d)\n", b);
|
||||
return 7 * b;
|
||||
}
|
||||
|
||||
void test6() {
|
||||
int fp = &f;
|
||||
int x = (*(int(*)()) fp)(10);
|
||||
printf("Function pointer result: %d\n", x);
|
||||
}
|
||||
|
||||
void test7() {
|
||||
int px = (int) malloc(120);
|
||||
* (float*) px = 8.8f;
|
||||
* (float*) (px + 4) = 9.9f;
|
||||
printf("Testing read/write (float*): %g %g\n", * (float*) px, * (float*) (px + 4));
|
||||
free((void*) px);
|
||||
}
|
||||
|
||||
void test8() {
|
||||
int px = (int) malloc(120);
|
||||
* (double*) px = 8.8;
|
||||
* (double*) (px + 8) = 9.9;
|
||||
printf("Testing read/write (double*): %g %g\n", * (double*) px, * (double*) (px + 8));
|
||||
free((void*) px);
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
test6();
|
||||
test7();
|
||||
test8();
|
||||
return 0;
|
||||
}
|
|
@ -77,7 +77,14 @@ def firstDifference(a, b):
|
|||
return i
|
||||
return commonLen
|
||||
|
||||
def compareSet(a1,a2,b1,b2):
|
||||
# a1 and a2 are the expected stdout and stderr.
|
||||
# b1 and b2 are the actual stdout and stderr.
|
||||
# Compare the two, sets. Allow any individual line
|
||||
# to appear in either stdout or stderr. This is because
|
||||
# the way we obtain output on the ARM combines both
|
||||
# streams into one sequence.
|
||||
|
||||
def compareOuput(a1,a2,b1,b2):
|
||||
while True:
|
||||
totalLen = len(a1) + len(a2) + len(b1) + len(b2)
|
||||
a1, b1 = matchCommon(a1, b1)
|
||||
|
@ -96,6 +103,8 @@ def compareSet(a1,a2,b1,b2):
|
|||
return False
|
||||
|
||||
def matchCommon(a, b):
|
||||
"""Remove common items from the beginning of a and b,
|
||||
return just the tails that are different."""
|
||||
while len(a) > 0 and len(b) > 0 and a[0] == b[0]:
|
||||
a = a[1:]
|
||||
b = b[1:]
|
||||
|
@ -105,25 +114,20 @@ def rewritePaths(args):
|
|||
return [rewritePath(x) for x in args]
|
||||
|
||||
def rewritePath(p):
|
||||
"""Take a path that's correct on the x86 and convert to a path
|
||||
that's correct on ARM."""
|
||||
if p.startswith("data/"):
|
||||
p = "/system/bin/accdata/" + p
|
||||
return p
|
||||
|
||||
class TestACC(unittest.TestCase):
|
||||
|
||||
def compileCheckOld(self, args, stdErrResult, stdOutResult=""):
|
||||
out, err = compile(args)
|
||||
compare(out, stdOutResult)
|
||||
compare(err, stdErrResult)
|
||||
self.assertEqual(out, stdOutResult)
|
||||
self.assertEqual(err, stdErrResult)
|
||||
|
||||
def checkResult(self, out, err, stdErrResult, stdOutResult=""):
|
||||
a1 = out.splitlines()
|
||||
a2 = err.splitlines()
|
||||
b2 = stdErrResult.splitlines()
|
||||
b1 = stdOutResult.splitlines()
|
||||
self.assertEqual(True, compareSet(a1,a2,b1,b2))
|
||||
self.assertEqual(True, compareOuput(a1,a2,b1,b2))
|
||||
|
||||
def compileCheck(self, args, stdErrResult, stdOutResult="",
|
||||
targets=['arm', 'x86']):
|
||||
|
@ -174,65 +178,77 @@ class TestACC(unittest.TestCase):
|
|||
|
||||
def testRunFlops(self):
|
||||
self.compileCheck(["-R", "data/flops.c"],
|
||||
"Executing compiled code:\nresult: 0\n",
|
||||
"-1.1 = -1.1\n" +
|
||||
"!1.2 = 0\n" +
|
||||
"!0 = 1\n" +
|
||||
"double op double:\n" +
|
||||
"1 + 2 = 3\n" +
|
||||
"1 - 2 = -1\n" +
|
||||
"1 * 2 = 2\n" +
|
||||
"1 / 2 = 0.5\n" +
|
||||
"float op float:\n" +
|
||||
"1 + 2 = 3\n" +
|
||||
"1 - 2 = -1\n" +
|
||||
"1 * 2 = 2\n" +
|
||||
"1 / 2 = 0.5\n" +
|
||||
"double op float:\n" +
|
||||
"1 + 2 = 3\n" +
|
||||
"1 - 2 = -1\n" +
|
||||
"1 * 2 = 2\n" +
|
||||
"1 / 2 = 0.5\n" +
|
||||
"double op int:\n" +
|
||||
"1 + 2 = 3\n" +
|
||||
"1 - 2 = -1\n" +
|
||||
"1 * 2 = 2\n" +
|
||||
"1 / 2 = 0.5\n" +
|
||||
"int op double:\n" +
|
||||
"1 + 2 = 3\n" +
|
||||
"1 - 2 = -1\n" +
|
||||
"1 * 2 = 2\n" +
|
||||
"1 / 2 = 0.5\n" +
|
||||
"double op double:\n" +
|
||||
"1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" +
|
||||
"1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" +
|
||||
"2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" +
|
||||
"double op float:\n" +
|
||||
"1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" +
|
||||
"1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" +
|
||||
"2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" +
|
||||
"float op float:\n" +
|
||||
"1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" +
|
||||
"1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" +
|
||||
"2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" +
|
||||
"int op double:\n" +
|
||||
"1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" +
|
||||
"1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" +
|
||||
"2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" +
|
||||
"double op int:\n" +
|
||||
"1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" +
|
||||
"1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" +
|
||||
"2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" +
|
||||
"branching: 1 0 1\n" +
|
||||
"testpassi: 1 2 3 4 5 6 7 8\n" +
|
||||
"testpassf: 1 2 3 4 5 6 7 8\n" +
|
||||
"testpassd: 1 2 3 4 5 6 7 8\n" +
|
||||
"testpassidf: 1 2 3\n"
|
||||
)
|
||||
|
||||
def oldtestArmRunReturnVal(self):
|
||||
self.compileCheckArm(["-R", "/system/bin/accdata/data/returnval-ansi.c"],
|
||||
"Executing compiled code:\nresult: 42\n")
|
||||
"""Executing compiled code:
|
||||
result: 0""",
|
||||
"""-1.1 = -1.1
|
||||
!1.2 = 0
|
||||
!0 = 1
|
||||
double op double:
|
||||
1 + 2 = 3
|
||||
1 - 2 = -1
|
||||
1 * 2 = 2
|
||||
1 / 2 = 0.5
|
||||
float op float:
|
||||
1 + 2 = 3
|
||||
1 - 2 = -1
|
||||
1 * 2 = 2
|
||||
1 / 2 = 0.5
|
||||
double op float:
|
||||
1 + 2 = 3
|
||||
1 - 2 = -1
|
||||
1 * 2 = 2
|
||||
1 / 2 = 0.5
|
||||
double op int:
|
||||
1 + 2 = 3
|
||||
1 - 2 = -1
|
||||
1 * 2 = 2
|
||||
1 / 2 = 0.5
|
||||
int op double:
|
||||
1 + 2 = 3
|
||||
1 - 2 = -1
|
||||
1 * 2 = 2
|
||||
1 / 2 = 0.5
|
||||
double op double:
|
||||
1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1
|
||||
1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0
|
||||
2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1
|
||||
double op float:
|
||||
1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1
|
||||
1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0
|
||||
2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1
|
||||
float op float:
|
||||
1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1
|
||||
1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0
|
||||
2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1
|
||||
int op double:
|
||||
1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1
|
||||
1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0
|
||||
2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1
|
||||
double op int:
|
||||
1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1
|
||||
1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0
|
||||
2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1
|
||||
branching: 1 0 1
|
||||
testpassi: 1 2 3 4 5 6 7 8
|
||||
testpassf: 1 2 3 4 5 6 7 8
|
||||
testpassd: 1 2 3 4 5 6 7 8
|
||||
testpassidf: 1 2 3
|
||||
""")
|
||||
def testCasts(self):
|
||||
self.compileCheck(["-R", "data/casts.c"],
|
||||
"""Executing compiled code:
|
||||
result: 0""", """Reading from a pointer: 3 3
|
||||
Writing to a pointer: 4
|
||||
Testing casts: 3 3 4.5 4
|
||||
Testing reading (int*): 4
|
||||
Testing writing (int*): 8 9
|
||||
Testing reading (char*): 0x78 0x56 0x34 0x12
|
||||
Testing writing (char*): 0x87654321
|
||||
f(10)
|
||||
Function pointer result: 70
|
||||
Testing read/write (float*): 8.8 9.9
|
||||
Testing read/write (double*): 8.8 9.9
|
||||
""")
|
||||
|
||||
if __name__ == '__main__':
|
||||
if not outputCanRun():
|
||||
|
|
Loading…
Reference in New Issue