Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 45431bc2 authored by Jack Palevich's avatar Jack Palevich
Browse files

Implement general casts and pointer dereferencing.

Prior to this casts and pointer dereferencing were special-cased.
parent 59178c0a
Loading
Loading
Loading
Loading
+27 −32
Original line number Diff line number Diff line
@@ -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 == '(') {
                // It's either a cast or an expression
                Type* pCast = acceptCastTypeDeclaration(mLocalArena);
                if (pCast) {
                    skip(')');
                    unary(false);
                    pGen->convertR0(pCast);
                } else {
                    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.
                /* This is a pointer dereference.
                 */
                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;
                unary(false);
                Type* pR0Type = pGen->getR0Type();
                if (pR0Type->tag != TY_POINTER) {
                    error("Expected a pointer type.");
                } else {
                    String buffer;
                    decodeType(buffer, pCast);
                    error("Unsupported cast type %s", buffer.getUnwrapped());
                    decodeType(buffer, mkpPtrIntFn);
                    if (pR0Type->pHead->tag == TY_FUNC) {
                        t = 0;
                    }
                skip(')');
                unary(false);
                    if (accept('=')) {
                        pGen->pushR0();
                        expr();
                    pGen->storeR0ToTOS(pCast);
                        pGen->storeR0ToTOS(pR0Type);
                    } else if (t) {
                    pGen->loadR0FromR0(pCast);
                        pGen->loadR0FromR0(pR0Type);
                    }
                }
                // Else we fall through to the function call below, with
                // t == 0 to trigger an indirect function call. Hack!
+85 −0
Original line number Diff line number Diff line
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;
}
+84 −68
Original line number Diff line number Diff line
@@ -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():