Merge change 1628
* changes:
Begin filling in ARM code generator.
diff --git a/libacc/Android.mk b/libacc/Android.mk
new file mode 100644
index 0000000..30f777a
--- /dev/null
+++ b/libacc/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+#
+# Shared library
+#
+
+LOCAL_MODULE:= acc
+LOCAL_SRC_FILES := acc.cpp
+
+include $(BUILD_EXECUTABLE)
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index 13a863f..0cc1a0f 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -27,6 +27,10 @@
#include <stdlib.h>
#include <string.h>
+#if defined(__arm__)
+#include <unistd.h>
+#endif
+
namespace acc {
class compiler {
@@ -65,6 +69,13 @@
}
}
+ int o4(int n) {
+ int result = (int) ind;
+ * (int*) ind = n;
+ ind += 4;
+ return result;
+ }
+
/*
* Output a byte. Handles all values, 0..ff.
*/
@@ -121,12 +132,12 @@
/* returns address to patch with local variable size
*/
- virtual int functionEntry() = 0;
+ virtual int functionEntry(int argCount) = 0;
- virtual void functionExit() = 0;
+ virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) = 0;
/* load immediate value */
- virtual int li(int t) = 0;
+ virtual void li(int t) = 0;
virtual int gjmp(int t) = 0;
@@ -135,7 +146,7 @@
virtual void gcmp(int op) = 0;
- virtual int genOp(int op) = 0;
+ virtual void genOp(int op) = 0;
virtual void clearECX() = 0;
@@ -172,6 +183,17 @@
pCodeBuf->gsym(t);
}
+ virtual int finishCompile() {
+#if defined(__arm__)
+ const long base = long(pCodeBuf->getBase());
+ const long curr = base + long(pCodeBuf->getSize());
+ int err = cacheflush(base, curr, 0);
+ return err;
+#else
+ return 0;
+#endif
+ }
+
protected:
void o(int n) {
pCodeBuf->o(n);
@@ -199,6 +221,9 @@
return pCodeBuf->getPC();
}
+ int o4(int data) {
+ return pCodeBuf->o4(data);
+ }
private:
CodeBuf* pCodeBuf;
};
@@ -208,21 +233,43 @@
ARMCodeGenerator() {}
virtual ~ARMCodeGenerator() {}
+ // The gnu ARM assembler prints the constants in little-endian,
+ // but C hexidecimal constants are big-endian. We trick the
+ // gnu assembler into putting out big-endian constants by
+ // using the -mbig-endian flag when assembling.
+
/* returns address to patch with local variable size
*/
- virtual int functionEntry() {
- fprintf(stderr, "functionEntry();\n");
- o(0xe58955); /* push %ebp, mov %esp, %ebp */
- return oad(0xec81, 0); /* sub $xxx, %esp */
+ virtual int functionEntry(int argCount) {
+ fprintf(stderr, "functionEntry(%d);\n", argCount);
+ /*
+ 19 0000 E1A0C00D mov ip, sp
+ 20 0004 E92DD800 stmfd sp!, {fp, ip, lr, pc}
+ 21 0008 E24CB004 sub fp, ip, #4
+ 22 000c E24DD008 sub sp, sp, #8
+ */
+ o4(0xE1A0C00D);
+ o4(0xE92DD800);
+ o4(0xE24CB004);
+ return o4(0xE24DD008);
}
- virtual void functionExit() {
- fprintf(stderr, "functionExit();\n");
- o(0xc3c9); /* leave, ret */
+ virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) {
+ fprintf(stderr, "functionExit(%d, %d, %d);\n", argCount, localVariableAddress, localVariableSize);
+ /*
+ 23 0010 E24BD00C sub sp, fp, #12
+ 24 0014 E89DA800 ldmfd sp, {fp, sp, pc}
+ */
+ o4(0xE24BD00C);
+ o4(0xE89DA800);
+ if (localVariableSize < 0 || localVariableSize > 255-8) {
+ error("LocalVariableSize");
+ }
+ *(char*) (localVariableAddress) = localVariableSize + 8;
}
/* load immediate value */
- virtual int li(int t) {
+ virtual void li(int t) {
fprintf(stderr, "li(%d);\n", t);
oad(0xb8, t); /* mov $xx, %eax */
}
@@ -251,7 +298,7 @@
#endif
}
- virtual int genOp(int op) {
+ virtual void genOp(int op) {
fprintf(stderr, "genOp(%d);\n", op);
#if 0
o(decodeOp(op));
@@ -352,6 +399,13 @@
private:
+ void error(const char* fmt,...) {
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ exit(12);
+ }
};
class X86CodeGenerator : public CodeGenerator {
@@ -361,17 +415,18 @@
/* returns address to patch with local variable size
*/
- virtual int functionEntry() {
+ virtual int functionEntry(int argCount) {
o(0xe58955); /* push %ebp, mov %esp, %ebp */
return oad(0xec81, 0); /* sub $xxx, %esp */
}
- virtual void functionExit() {
+ virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) {
o(0xc3c9); /* leave, ret */
+ *(int *) localVariableAddress = localVariableSize; /* save local variables */
}
/* load immediate value */
- virtual int li(int t) {
+ virtual void li(int t) {
oad(0xb8, t); /* mov $xx, %eax */
}
@@ -394,7 +449,7 @@
o(0xc0);
}
- virtual int genOp(int op) {
+ virtual void genOp(int op) {
o(decodeOp(op));
if (op == OP_MOD)
o(0x92); /* xchg %edx, %eax */
@@ -478,7 +533,7 @@
return operatorHelper[op];
}
- int gmov(int l, int t) {
+ void gmov(int l, int t) {
o(l + 0x83);
oad((t < LOCAL) << 7 | 5, t);
}
@@ -578,7 +633,7 @@
}
int isid() {
- return isalnum(ch) | ch == '_';
+ return isalnum(ch) | (ch == '_');
}
/* read a character constant */
@@ -593,7 +648,7 @@
void next() {
int l, a;
- while (isspace(ch) | ch == '#') {
+ while (isspace(ch) | (ch == '#')) {
if (ch == '#') {
inp();
next();
@@ -653,7 +708,7 @@
tokc = ch;
inp();
inp();
- } else if (tok == '/' & ch == '*') {
+ } else if ((tok == '/') & (ch == '*')) {
inp();
while (ch) {
while (ch != '*')
@@ -667,11 +722,11 @@
} else {
const char* t = operatorChars;
int opIndex = 0;
- while (l = *t++) {
+ while ((l = *t++) != 0) {
a = *t++;
tokl = operatorLevel[opIndex];
tokc = opIndex;
- if (l == tok & (a == ch | a == '@')) {
+ if ((l == tok) & ((a == ch) | (a == '@'))) {
#if 0
printf("%c%c -> tokl=%d tokc=0x%x\n",
l, a, tokl, tokc);
@@ -734,7 +789,7 @@
/* l is one if '=' parsing wanted (quick hack) */
void unary(int l) {
int n, t, a, c;
-
+ t = 0;
n = 1; /* type of expression 0 = forward, 1 = value, other =
lvalue */
if (tok == '\"') {
@@ -745,7 +800,7 @@
inp();
}
*(char *) glo = 0;
- glo = glo + 4 & -4; /* align heap */
+ glo = (glo + 4) & -4; /* align heap */
inp();
next();
} else {
@@ -799,7 +854,7 @@
/* forward reference: try dlsym */
if (!n)
n = (int) dlsym(0, (char*) last_id);
- if (tok == '=' & l) {
+ if ((tok == '=') & l) {
/* assignment */
next();
expr();
@@ -850,7 +905,7 @@
void sum(int l) {
int t, n, a;
-
+ t = 0;
if (l-- == 1)
unary(1);
else {
@@ -869,7 +924,7 @@
sum(l);
pGen->popECX();
- if (l == 4 | l == 5) {
+ if ((l == 4) | (l == 5)) {
pGen->gcmp(t);
} else {
pGen->genOp(t);
@@ -914,7 +969,7 @@
} else {
pGen->gsym(a); /* patch if test */
}
- } else if (tok == TOK_WHILE | tok == TOK_FOR) {
+ } else if ((tok == TOK_WHILE) | (tok == TOK_FOR)) {
t = tok;
next();
skip('(');
@@ -968,7 +1023,7 @@
void decl(int l) {
int a;
- while (tok == TOK_INT | tok != -1 & !l) {
+ while ((tok == TOK_INT) | ((tok != -1) & (!l))) {
if (tok == TOK_INT) {
next();
while (tok != ';') {
@@ -993,6 +1048,7 @@
next();
skip('(');
a = 8;
+ int argCount = 0;
while (tok != ')') {
/* read param name and compute offset */
*(int *) tok = a;
@@ -1000,14 +1056,14 @@
next();
if (tok == ',')
next();
+ argCount++;
}
next(); /* skip ')' */
rsym = loc = 0;
- a = pGen->functionEntry();
+ a = pGen->functionEntry(argCount);
block(0);
pGen->gsym(rsym);
- pGen->functionExit();
- *(int *) a = loc; /* save local variables */
+ pGen->functionExit(argCount, a, loc);
}
}
}
@@ -1104,6 +1160,7 @@
inp();
next();
decl(0);
+ pGen->finishCompile();
return 0;
}
@@ -1162,6 +1219,11 @@
} // namespace acc
+// This is a separate function so it can easily be set by breakpoint in gdb.
+int run(acc::compiler& c, int argc, char** argv) {
+ return c.run(argc, argv);
+}
+
int main(int argc, char** argv) {
bool doDump = false;
const char* inFile = NULL;
@@ -1232,7 +1294,7 @@
int codeArgc = argc - i + 1;
char** codeArgv = argv + i - 1;
codeArgv[0] = (char*) (inFile ? inFile : "stdin");
- int result = compiler.run(codeArgc, codeArgv);
+ int result = run(compiler, codeArgc, codeArgv);
fprintf(stderr, "result: %d\n", result);
return result;
}
diff --git a/libacc/test b/libacc/test
index be883a6..8bf33c8 100755
--- a/libacc/test
+++ b/libacc/test
@@ -1,3 +1,3 @@
#!/bin/sh
-g++ acc.cpp -ldl -o tests/acc && tests/acc tests/otcc.c -a x86 -d tests/otcc.out && diff tests/otcc.out tests/otcc.out-orig
+g++ acc.cpp -g -ldl -o tests/acc && tests/acc tests/otcc.c -a x86 -d tests/otcc.out && diff tests/otcc.out tests/otcc.out-orig
tests/acc tests/simplest.c
diff --git a/libacc/tests/otcc.out-orig b/libacc/tests/otcc.out-orig
index 3bf7e1f..6b8bd59 100644
--- a/libacc/tests/otcc.out-orig
+++ b/libacc/tests/otcc.out-orig
Binary files differ