Add support for "short" data type.

This commit is contained in:
Jack Palevich 2009-08-03 14:42:57 -07:00
parent 029c7f81a9
commit c9b8ffc389
5 changed files with 115 additions and 28 deletions

View File

@ -1,6 +1,5 @@
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 ('*') only works with explicit cast to
'char *', 'int *' or 'int (*)()' (function pointer).
* Pointer indirection ('*') is supported.
* '++', '--', and unary '&' can only be used with variable
lvalue (left value).
* Square brackets can be used for pointer arithmetic.
* '=' can only be used with variable or '*' (pointer
indirection) lvalue.
* '=' and <op>= are supported.
* Function calls are supported with standard i386 calling
convention. Function pointers are supported with explicit
cast. Functions can be used before being declared.
* Function calls are supported with standard Linux calling
convention. Function pointers are supported.
Functions can be used before being declared.
- 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).
- sizeof() is not supported.
- Any function or variable from the libc can be used because OTCC
uses the libc dynamic linker to resolve undefined symbols.
- 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
- 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).

View File

@ -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);

View File

@ -0,0 +1,6 @@
short a = 3;
int main() {
short* b = &a;
*b = *b - 5;
return a;
}

View File

@ -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);
}

View File

@ -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__':