Implement architecture-dependent defaults.

If libacc is built on x86, then x86 is the default code generator.
If libacc is built on arm. then ARM is the default code generator
And so on for future architectures.

The 64-bit x64 machine has no working code generator currently.
We may add one to support the simulator builds.

Improved the test program so we don't try to run tests if the
compile failed. Also avoid running tests that don't work on
a given platform.
This commit is contained in:
Jack Palevich 2009-05-19 17:12:17 -07:00
parent 274663bf67
commit e7b590666d
2 changed files with 113 additions and 66 deletions

View File

@ -1,3 +1,14 @@
/*
* Android "Almost" C Compiler.
* This is a compiler for a small subset of the C language, intended for use
* in scripting environments where speed and memory footprint are important.
*
* This code is based upon the "unobfuscated" version of the
* Obfuscated Tiny C compiler, and retains the
* original copyright notice and license from that compiler, see below.
*
*/
/*
Obfuscated Tiny C Compiler
@ -31,11 +42,24 @@
#include <unistd.h>
#endif
#if defined(__arm__)
#define DEFAULT_ARM_CODEGEN
#elif defined(__i386__)
#define DEFAULT_X86_CODEGEN
#elif defined(__x86_64__)
#define DEFAULT_X64_CODEGEN
#endif
#define PROVIDE_X86_CODEGEN
#define PROVIDE_ARM_CODEGEN
#ifdef PROVIDE_ARM_CODEGEN
#include "disassem.h"
#endif
namespace acc {
class compiler {
class Compiler {
class CodeBuf {
char* ind;
char* pProgramBase;
@ -63,14 +87,6 @@ class compiler {
ind = pProgramBase;
}
void o(int n) {
/* cannot use unsigned, so we must do a hack */
while (n && n != -1) {
*ind++ = n;
n = n >> 8;
}
}
int o4(int n) {
int result = (int) ind;
* (int*) ind = n;
@ -85,31 +101,6 @@ class compiler {
*ind++ = n;
}
/* output a symbol and patch all calls to it */
void gsym(int t) {
int n;
while (t) {
n = *(int *) t; /* next value */
*(int *) t = ((int) ind) - t - 4;
t = n;
}
}
/* psym is used to put an instruction with a data field which is a
reference to a symbol. It is in fact the same as oad ! */
int psym(int n, int t) {
return oad(n, t);
}
/* instruction + address */
int oad(int n, int t) {
o(n);
*(int *) ind = t;
t = (int) ind;
ind = ind + 4;
return t;
}
inline void* getBase() {
return (void*) pProgramBase;
}
@ -184,9 +175,7 @@ class compiler {
virtual int disassemble(FILE* out) = 0;
/* output a symbol and patch all calls to it */
virtual void gsym(int t) {
pCodeBuf->gsym(t);
}
virtual void gsym(int t) = 0;
virtual int finishCompile() {
#if defined(__arm__)
@ -205,10 +194,6 @@ class compiler {
virtual int jumpOffset() = 0;
protected:
void o(int n) {
pCodeBuf->o(n);
}
/*
* Output a byte. Handles all values, 0..ff.
*/
@ -216,15 +201,8 @@ class compiler {
pCodeBuf->ob(n);
}
/* psym is used to put an instruction with a data field which is a
reference to a symbol. It is in fact the same as oad ! */
int psym(int n, int t) {
return oad(n, t);
}
/* instruction + address */
int oad(int n, int t) {
return pCodeBuf->oad(n,t);
int o4(int data) {
return pCodeBuf->o4(data);
}
int getBase() {
@ -234,14 +212,12 @@ class compiler {
int getPC() {
return pCodeBuf->getPC();
}
int o4(int data) {
return pCodeBuf->o4(data);
}
private:
CodeBuf* pCodeBuf;
};
#ifdef PROVIDE_ARM_CODEGEN
class ARMCodeGenerator : public CodeGenerator {
public:
ARMCodeGenerator() {}
@ -701,6 +677,10 @@ class compiler {
}
};
#endif // PROVIDE_X86_CODEGEN
#ifdef PROVIDE_X86_CODEGEN
class X86CodeGenerator : public CodeGenerator {
public:
X86CodeGenerator() {}
@ -829,7 +809,45 @@ class compiler {
return 1;
}
/* output a symbol and patch all calls to it */
virtual void gsym(int t) {
int n;
int pc = getPC();
while (t) {
n = *(int *) t; /* next value */
*(int *) t = pc - t - 4;
t = n;
}
}
private:
/** Output 1 to 4 bytes.
*
*/
void o(int n) {
/* cannot use unsigned, so we must do a hack */
while (n && n != -1) {
ob(n & 0xff);
n = n >> 8;
}
}
/* psym is used to put an instruction with a data field which is a
reference to a symbol. It is in fact the same as oad ! */
int psym(int n, int t) {
return oad(n, t);
}
/* instruction + address */
int oad(int n, int t) {
o(n);
int result = getPC();
o4(t);
return result;
}
static const int operatorHelper[];
int decodeOp(int op) {
@ -846,6 +864,8 @@ class compiler {
}
};
#endif // PROVIDE_X86_CODEGEN
/* vars: value of variables
loc : local variable index
glo : global variable index
@ -1426,16 +1446,31 @@ class compiler {
if (architecture != NULL) {
if (strcmp(architecture, "arm") == 0) {
#ifdef PROVIDE_ARM_CODEGEN
pGen = new ARMCodeGenerator();
#else
fprintf(stderr, "Unsupported architecture %s", architecture);
#endif
} else if (strcmp(architecture, "x86") == 0) {
#ifdef PROVIDE_X86_CODEGEN
pGen = new X86CodeGenerator();
#else
fprintf(stderr, "Unsupported architecture %s", architecture);
#endif
} else {
fprintf(stderr, "Unknown architecture %s", architecture);
}
}
if (pGen == NULL) {
#if defined(DEFAULT_ARM_CODEGEN)
pGen = new ARMCodeGenerator();
#elif defined(DEFAULT_X86_CODEGEN)
pGen = new X86CodeGenerator();
#endif
}
if (pGen == NULL) {
fprintf(stderr, "No code generator defined.");
}
}
@ -1447,11 +1482,11 @@ public:
const char* architecture;
};
compiler() {
Compiler() {
clear();
}
~compiler() {
~Compiler() {
cleanup();
}
@ -1498,10 +1533,10 @@ public:
};
const char* compiler::operatorChars =
const char* Compiler::operatorChars =
"++--*@/@%@+@-@<<>><=>=<@>@==!=&&||&@^@|@~@!@";
const char compiler::operatorLevel[] =
const char Compiler::operatorLevel[] =
{11, 11, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4,
5, 5, /* ==, != */
9, 10, /* &&, || */
@ -1509,9 +1544,9 @@ const char compiler::operatorLevel[] =
2, 2 /* ~ ! */
};
FILE* compiler::ARMCodeGenerator::disasmOut;
FILE* Compiler::ARMCodeGenerator::disasmOut;
const int compiler::X86CodeGenerator::operatorHelper[] = {
const int Compiler::X86CodeGenerator::operatorHelper[] = {
0x1, // ++
0xff, // --
0xc1af0f, // *
@ -1539,7 +1574,7 @@ const int compiler::X86CodeGenerator::operatorHelper[] = {
} // 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) {
int run(acc::Compiler& c, int argc, char** argv) {
return c.run(argc, argv);
}
@ -1548,7 +1583,7 @@ int main(int argc, char** argv) {
bool doDisassemble = false;
const char* inFile = NULL;
const char* outFile = NULL;
const char* architecture = "arm";
const char* architecture = NULL;
int i;
for (i = 1; i < argc; i++) {
char* arg = argv[i];
@ -1593,9 +1628,11 @@ int main(int argc, char** argv) {
return 1;
}
}
acc::compiler compiler;
acc::compiler::args args;
args.architecture = architecture;
acc::Compiler compiler;
acc::Compiler::args args;
if (architecture != NULL) {
args.architecture = architecture;
}
int compileResult = compiler.compile(in, args);
if (in != stdin) {
fclose(in);

View File

@ -1,3 +1,13 @@
#!/bin/sh
rm -f tests/acc
g++ acc.cpp disassem.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 -S tests/returnval.c
if [ -x "tests/acc" ]; then
tests/acc -S tests/returnval.c
if [ "$(uname)" = "Linux" ]; then
if [ "$(uname -m)" = "i686" ]; then
echo "Linux i686. Testing otcc.c"
tests/acc tests/otcc.c tests/otcc.c tests/returnval.c
fi
fi
fi