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

Commit c9b8ffc3 authored by Jack Palevich's avatar Jack Palevich
Browse files

Add support for "short" data type.

parent 029c7f81
Loading
Loading
Loading
Loading
+40 −22
Original line number Diff line number Diff line

Supported C language subset (read joint example 'otccex.c' to have
    an introduction to OTCC dialect):
Supported C language subset:

    - Expressions:

@@ -13,35 +12,51 @@ Supported C language subset (read joint example 'otccex.c' to have

        * Parenthesis are supported.

        * Comma operator is supported.

        * Trinary operator (?:) is not supported.

        * Unary operators: '&', '*' (pointer indirection), '-'
          (negation), '+', '!', '~', post fixed '++' and '--'.
          (negation), '+', '!', '~', '++' and '--'.

        * Pointer indirection ('*') is supported.

        * Pointer indirection ('*') only works with explicit cast to
          'char *', 'int *' or 'int (*)()' (function pointer).
        * Square brackets can be used for pointer arithmetic.

        * '++', '--', and unary '&' can only be used with variable
          lvalue (left value).
        * '=' and <op>= are supported.

        * '=' can only be used with variable or '*' (pointer
          indirection) lvalue.
        * Function calls are supported with standard Linux calling
          convention. Function pointers are supported.
          Functions can be used before being declared.

        * Function calls are supported with standard i386 calling
          convention. Function pointers are supported with explicit
          cast. Functions can be used before being declared.
        - sizeof() is not supported.

    - Types: only signed integer ('int') variables and functions can
      be declared. Variables cannot be initialized in
      declarations. Only old K&R function declarations are parsed
      (implicit integer return value and no types on arguments).
    - Types:
        + int, short, char, float, double
        + pointers
        + variables can be initialized in declarations.
        + Only ANSI-style function declarations are supported.
           - "..." is not supported.
        - short is not supported
        - const is not supported
        - arrays are not supported
        - long doubles are not supported
        - structs are not supported

    - Any function or variable from the libc can be used because OTCC
      uses the libc dynamic linker to resolve undefined symbols.
    - Unknown functions and variables are bound at compile time by calling
      back to the caller. For the 'acc' command-line tool unknown functions
      and variables are looked up using dlsym, to allow using many libc
      functions and variables.

    - Instructions: blocks ('{' '}') are supported as in C. 'if' and
      'else' can be used for tests. The 'while' and 'for' C constructs
      are supported for loops. 'break' can be used to exit
      loops. 'return' is used for the return value of a function.

      - switch / case is not supported.
      - goto and labels are not supported.
      - continue is not supported.

    - Identifiers are parsed the same way as C. Local variables are
      handled, but there is no local name space (not a problem if
      different names are used for local and global variables).
@@ -49,16 +64,19 @@ Supported C language subset (read joint example 'otccex.c' to have
    - Numbers can be entered in decimal, hexadecimal ('0x' or '0X'
      prefix), or octal ('0' prefix).

    - Float and double constants are supported.

    - '#define' is supported without function like arguments. No macro
      recursion is tolerated. Other preprocessor directives are
      ignored.

    - C Strings and C character constants are supported. Only '\n',
      '\"', '\'' and '\\' escapes are recognized.
    - C Strings and C character constants are supported. All ANSI C
      character escapes are supported.

    - Both C comments ( /* */ ) and C++ comments ( // ... end-of-line ) can be used.
    - Both C comments ( /* */ ) and C++ comments ( // ... end-of-line ) are
      supported.

    - No error is displayed if an incorrect program is given.
    - Some syntax errors are reported, others may cause a crash.

    - Memory: the code, data, and symbol sizes are limited to 100KB
      (it can be changed in the source code).
+56 −6
Original line number Diff line number Diff line
@@ -133,13 +133,22 @@ public:
class Compiler : public ErrorSink {
    typedef int tokenid_t;
    enum TypeTag {
        TY_INT, TY_CHAR, TY_VOID, TY_FLOAT, TY_DOUBLE,
        TY_POINTER, TY_FUNC, TY_PARAM
        TY_INT,       // 0
        TY_CHAR,      // 1
        TY_SHORT,     // 2
        TY_VOID,      // 3
        TY_FLOAT,     // 4
        TY_DOUBLE,    // 5
        TY_POINTER, // 6
        TY_ARRAY,   // 7
        TY_STRUCT,  // 8
        TY_FUNC,    // 9
        TY_PARAM    // 10
    };

    struct Type {
        TypeTag tag;
        tokenid_t id; // For function arguments
        tokenid_t id; // For function arguments (stores length for array)
        Type* pHead;
        Type* pTail;
    };
@@ -594,8 +603,18 @@ class Compiler : public ErrorSink {

        TypeTag collapseType(TypeTag tag) {
            static const TypeTag collapsedTag[] = {
                    TY_INT, TY_INT, TY_VOID, TY_FLOAT, TY_DOUBLE, TY_INT,
                    TY_VOID, TY_VOID};
                    TY_INT,
                    TY_INT,
                    TY_INT,
                    TY_VOID,
                    TY_FLOAT,
                    TY_DOUBLE,
                    TY_INT,
                    TY_INT,
                    TY_VOID,
                    TY_VOID,
                    TY_VOID
                };
            return collapsedTag[tag];
        }

@@ -1093,6 +1112,9 @@ class Compiler : public ErrorSink {
                case TY_FLOAT:
                    o4(0xE5820000); // str r0, [r2]
                    break;
                case TY_SHORT:
                    o4(0xE1C200B0); // strh r0, [r2]
                    break;
                case TY_CHAR:
                    o4(0xE5C20000); // strb r0, [r2]
                    break;
@@ -1115,6 +1137,9 @@ class Compiler : public ErrorSink {
                case TY_FLOAT:
                    o4(0xE5900000); // ldr r0, [r0]
                    break;
                case TY_SHORT:
                    o4(0xE1D000F0); // ldrsh r0, [r0]
                    break;
                case TY_CHAR:
                    o4(0xE5D00000); // ldrb r0, [r0]
                    break;
@@ -1378,6 +1403,8 @@ class Compiler : public ErrorSink {
            switch(pType->tag) {
                case TY_CHAR:
                    return 1;
                case TY_SHORT:
                    return 1;
                case TY_DOUBLE:
                    return 8;
                default:
@@ -1392,6 +1419,8 @@ class Compiler : public ErrorSink {
            switch(pType->tag) {
                case TY_INT:
                    return 4;
                case TY_SHORT:
                    return 2;
                case TY_CHAR:
                    return 1;
                default:
@@ -2095,6 +2124,9 @@ class Compiler : public ErrorSink {
                case TY_INT:
                    o(0x0189); /* movl %eax/%al, (%ecx) */
                    break;
                case TY_SHORT:
                    o(0x018966); /* movw %ax, (%ecx) */
                    break;
                case TY_CHAR:
                    o(0x0188); /* movl %eax/%al, (%ecx) */
                    break;
@@ -2119,6 +2151,10 @@ class Compiler : public ErrorSink {
                case TY_INT:
                    o2(0x008b); /* mov (%eax), %eax */
                    break;
                case TY_SHORT:
                    o(0xbf0f); /* movswl (%eax), %eax */
                    ob(0);
                    break;
                case TY_CHAR:
                    o(0xbe0f); /* movsbl (%eax), %eax */
                    ob(0); /* add zero in code */
@@ -2288,6 +2324,8 @@ class Compiler : public ErrorSink {
            switch (pType->tag) {
            case TY_CHAR:
                return 1;
            case TY_SHORT:
                return 2;
            default:
                return 4;
            }
@@ -2300,6 +2338,8 @@ class Compiler : public ErrorSink {
            switch(pType->tag) {
                case TY_INT:
                    return 4;
                case TY_SHORT:
                    return 2;
                case TY_CHAR:
                    return 1;
                default:
@@ -3158,6 +3198,7 @@ class Compiler : public ErrorSink {

    // Prebuilt types, makes things slightly faster.
    Type* mkpInt;        // int
    Type* mkpShort;      // short
    Type* mkpChar;       // char
    Type* mkpVoid;       // void
    Type* mkpFloat;
@@ -4013,7 +4054,8 @@ class Compiler : public ErrorSink {
        pGen->pushR0();
        pGen->loadR0FromR0();
        int tag = pGen->getR0Type()->tag;
        if (!(tag == TY_INT || tag == TY_CHAR || tag == TY_POINTER)) {
        if (!(tag == TY_INT || tag == TY_SHORT || tag == TY_CHAR ||
                tag == TY_POINTER)) {
            error("++/-- illegal for this type. %d", tag);
        }
        if (isPost) {
@@ -4262,6 +4304,9 @@ class Compiler : public ErrorSink {
                case TY_INT:
                    buffer.appendCStr("int");
                    break;
                case TY_SHORT:
                    buffer.appendCStr("short");
                    break;
                case TY_CHAR:
                    buffer.appendCStr("char");
                    break;
@@ -4283,6 +4328,8 @@ class Compiler : public ErrorSink {
        switch (tag) {
            case TY_INT:
                break;
            case TY_SHORT:
                break;
            case TY_CHAR:
                break;
            case TY_VOID:
@@ -4347,6 +4394,8 @@ class Compiler : public ErrorSink {
        Type* pType;
        if (tok == TOK_INT) {
            pType = mkpInt;
        } else if (tok == TOK_SHORT) {
            pType = mkpShort;
        } else if (tok == TOK_CHAR) {
            pType = mkpChar;
        } else if (tok == TOK_VOID) {
@@ -4844,6 +4893,7 @@ public:

    void createPrimitiveTypes() {
        mkpInt = createType(TY_INT, NULL, NULL);
        mkpShort = createType(TY_SHORT, NULL, NULL);
        mkpChar = createType(TY_CHAR, NULL, NULL);
        mkpVoid = createType(TY_VOID, NULL, NULL);
        mkpFloat = createType(TY_FLOAT, NULL, NULL);
+6 −0
Original line number Diff line number Diff line
short a = 3;
int main() {
    short* b = &a;
    *b = *b - 5;
    return a;
}
+8 −0
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@ void run(ScriptPtr scriptFn) {
extern "C"
void accDisassemble(ACCscript* script);

int globalVar;

void op_int(int a) {
    printf("op_int(%d)\n", a);
}
@@ -46,6 +48,7 @@ const char* text = "void op_int(int a);\n"
    "           float e, float f, float g, float h,\n"
    "           float i, float j, float k, float l);\n"
    "void script() {\n"
    "  globalVar += 3;\n"
    "  op_int(123);\n"
    "  op_float12(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0);\n"
    "}\n";
@@ -57,6 +60,9 @@ ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) {
    if (strcmp("op_float12", name) == 0) {
        return (ACCvoid*) op_float12;
    }
    if (strcmp("globalVar", name) == 0) {
        return (ACCvoid*) &globalVar;
    }
    return (ACCvoid*) dlsym(RTLD_DEFAULT, name);
}

@@ -98,7 +104,9 @@ int main(int argc, char** argv) {
        fprintf(stderr, "Could not find script: %d\n", result);
    } else {
        fprintf(stderr, "Executing script:\n");
        globalVar = 17;
        run(scriptPointer);
        fprintf(stderr, "After script globalVar = %d\n", globalVar);
    }


+5 −0
Original line number Diff line number Diff line
@@ -380,6 +380,11 @@ arg: 12
Errors: 0
2D Errors: 0
result: 0
""","""""")

    def testShort(self):
        self.compileCheck(["-R", "data/short.c"], """Executing compiled code:
result: -2
""","""""")

if __name__ == '__main__':