Add support for "short" data type.
diff --git a/libacc/FEATURES b/libacc/FEATURES
index 1a44415..97a876d 100644
--- a/libacc/FEATURES
+++ b/libacc/FEATURES
@@ -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 @@
* 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 @@
- 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).
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index 676947e..313bf1c 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -133,13 +133,22 @@
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 @@
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 @@
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 @@
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 @@
switch(pType->tag) {
case TY_CHAR:
return 1;
+ case TY_SHORT:
+ return 1;
case TY_DOUBLE:
return 8;
default:
@@ -1392,6 +1419,8 @@
switch(pType->tag) {
case TY_INT:
return 4;
+ case TY_SHORT:
+ return 2;
case TY_CHAR:
return 1;
default:
@@ -2095,6 +2124,9 @@
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 @@
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 @@
switch (pType->tag) {
case TY_CHAR:
return 1;
+ case TY_SHORT:
+ return 2;
default:
return 4;
}
@@ -2300,6 +2338,8 @@
switch(pType->tag) {
case TY_INT:
return 4;
+ case TY_SHORT:
+ return 2;
case TY_CHAR:
return 1;
default:
@@ -3158,6 +3198,7 @@
// Prebuilt types, makes things slightly faster.
Type* mkpInt; // int
+ Type* mkpShort; // short
Type* mkpChar; // char
Type* mkpVoid; // void
Type* mkpFloat;
@@ -4013,7 +4054,8 @@
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 @@
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 @@
switch (tag) {
case TY_INT:
break;
+ case TY_SHORT:
+ break;
case TY_CHAR:
break;
case TY_VOID:
@@ -4347,6 +4394,8 @@
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 @@
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);
diff --git a/libacc/tests/data/short.c b/libacc/tests/data/short.c
new file mode 100644
index 0000000..5e222f3
--- /dev/null
+++ b/libacc/tests/data/short.c
@@ -0,0 +1,6 @@
+short a = 3;
+int main() {
+ short* b = &a;
+ *b = *b - 5;
+ return a;
+}
diff --git a/libacc/tests/runtimeTest.cpp b/libacc/tests/runtimeTest.cpp
index d59e1d1..55bf877 100644
--- a/libacc/tests/runtimeTest.cpp
+++ b/libacc/tests/runtimeTest.cpp
@@ -30,6 +30,8 @@
extern "C"
void accDisassemble(ACCscript* script);
+int globalVar;
+
void op_int(int a) {
printf("op_int(%d)\n", a);
}
@@ -46,6 +48,7 @@
" 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 @@
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 @@
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);
}
diff --git a/libacc/tests/test.py b/libacc/tests/test.py
index 7bcbdd4..a3114ad 100644
--- a/libacc/tests/test.py
+++ b/libacc/tests/test.py
@@ -382,6 +382,11 @@
result: 0
""","""""")
+ def testShort(self):
+ self.compileCheck(["-R", "data/short.c"], """Executing compiled code:
+result: -2
+""","""""")
+
if __name__ == '__main__':
if not outputCanRun():
print "Many tests are expected to fail, because acc is not a 32-bit x86 Linux executable."