diff options
| author | Android (Google) Code Review <android-gerrit@google.com> | 2009-07-06 18:42:51 -0700 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2009-07-06 18:42:51 -0700 |
| commit | 1816655869824cbb17db01bdcb928cfad95937cc (patch) | |
| tree | b1b202aaf4167c511a3bfff2330d9558874f3de6 /libacc/acc.cpp | |
| parent | 73aaaac1044fe745158d0d5899bd8c7af8fe6806 (diff) | |
| parent | 9eed7a2c7b3748f4aa10e1dc60875bf72a18c275 (diff) | |
| download | system_core-1816655869824cbb17db01bdcb928cfad95937cc.zip system_core-1816655869824cbb17db01bdcb928cfad95937cc.tar.gz system_core-1816655869824cbb17db01bdcb928cfad95937cc.tar.bz2 | |
Merge change 6322
* changes:
Start teaching the code generator about types.
Diffstat (limited to 'libacc/acc.cpp')
| -rw-r--r-- | libacc/acc.cpp | 316 |
1 files changed, 240 insertions, 76 deletions
diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 0209031..7547fde 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -68,6 +68,8 @@ public: }; class Compiler : public ErrorSink { + struct Type; + class CodeBuf { char* ind; // Output code pointer char* pProgramBase; @@ -157,8 +159,7 @@ class Compiler : public ErrorSink { * architecture. * * The code generator implements the following abstract machine: - * R0 - the main accumulator. - * R1 - the secondary accumulator. + * R0 - the accumulator. * FP - a frame pointer for accessing function arguments and local * variables. * SP - a stack pointer for storing intermediate results while evaluating @@ -168,7 +169,7 @@ class Compiler : public ErrorSink { * stack such that the first argument has the lowest address. * After the call, the result is in R0. The caller is responsible for * removing the arguments from the stack. - * The R0 and R1 registers are not saved across function calls. The + * The R0 register is not saved across function calls. The * FP and SP registers are saved. */ @@ -232,41 +233,42 @@ class Compiler : public ErrorSink { */ virtual int gtst(bool l, int t) = 0; - /* Compare R1 against R0, and store the boolean result in R0. + /* Compare TOS against R0, and store the boolean result in R0. + * Pops TOS. * op specifies the comparison. */ virtual void gcmp(int op) = 0; - /* Perform the arithmetic op specified by op. R1 is the + /* Perform the arithmetic op specified by op. TOS is the * left argument, R0 is the right argument. + * Pops TOS. */ virtual void genOp(int op) = 0; - /* Set R1 to 0. + /* Compare 0 against R0, and store the boolean result in R0. + * op specifies the comparison. */ - virtual void clearR1() = 0; + virtual void gUnaryCmp(int op) = 0; - /* Push R0 onto the stack. + /* Perform the arithmetic op specified by op. 0 is the + * left argument, R0 is the right argument. */ - virtual void pushR0() = 0; + virtual void genUnaryOp(int op) = 0; - /* Pop R1 off of the stack. + /* Push R0 onto the stack. */ - virtual void popR1() = 0; + virtual void pushR0() = 0; - /* Store R0 to the address stored in R1. - * isInt is true if a whole 4-byte integer value - * should be stored, otherwise a 1-byte character - * value should be stored. + /* Store R0 to the address stored in TOS. + * The TOS is popped. + * pPointerType is the type of the pointer (of the input R0). */ - virtual void storeR0ToR1(bool isInt) = 0; + virtual void storeR0ToTOS(Type* pPointerType) = 0; /* Load R0 from the address stored in R0. - * isInt is true if a whole 4-byte integer value - * should be loaded, otherwise a 1-byte character - * value should be loaded. + * pPointerType is the type of the pointer (of the input R0). */ - virtual void loadR0FromR0(bool isInt) = 0; + virtual void loadR0FromR0(Type* pPointerType) = 0; /* Load the absolute address of a variable to R0. * If ea <= LOCAL, then this is a local variable, or an @@ -362,6 +364,16 @@ class Compiler : public ErrorSink { */ virtual int jumpOffset() = 0; + /** + * Stack alignment (in bytes) for this type of data + */ + virtual size_t stackAlignment(Type* type) = 0; + + /** + * Array element alignment (in bytes) for this type of data. + */ + virtual size_t sizeOf(Type* type) = 0; + protected: /* * Output a byte. Handles all values, 0..ff. @@ -392,6 +404,12 @@ class Compiler : public ErrorSink { mErrorSink->verror(fmt, ap); va_end(ap); } + + void assert(bool test) { + if (!test) { + error("code generator assertion failed."); + } + } private: CodeBuf* pCodeBuf; ErrorSink* mErrorSink; @@ -489,6 +507,8 @@ class Compiler : public ErrorSink { virtual void gcmp(int op) { LOG_API("gcmp(%d);\n", op); + o4(0xE8BD0002); // ldmfd sp!,{r1} + mStackUse -= 4; o4(0xE1510000); // cmp r1, r1 switch(op) { case OP_EQUALS: @@ -523,6 +543,8 @@ class Compiler : public ErrorSink { virtual void genOp(int op) { LOG_API("genOp(%d);\n", op); + o4(0xE8BD0002); // ldmfd sp!,{r1} + mStackUse -= 4; switch(op) { case OP_MUL: o4(0x0E0000091); // mul r0,r1,r0 @@ -563,9 +585,38 @@ class Compiler : public ErrorSink { } } - virtual void clearR1() { - LOG_API("clearR1();\n"); + virtual void gUnaryCmp(int op) { + LOG_API("gcmp(%d);\n", op); o4(0xE3A01000); // mov r1, #0 + o4(0xE1510000); // cmp r1, r1 + switch(op) { + case OP_NOT_EQUALS: + o4(0x03A00000); // moveq r0,#0 + o4(0x13A00001); // movne r0,#1 + break; + default: + error("Unknown unary comparison op %d", op); + break; + } + } + + virtual void genUnaryOp(int op) { + LOG_API("genOp(%d);\n", op); + switch(op) { + case OP_PLUS: + // Do nothing + break; + case OP_MINUS: + o4(0xE3A01000); // mov r1, #0 + o4(0xE0410000); // sub r0,r1,r0 + break; + case OP_BIT_NOT: + o4(0xE1E00000); // mvn r0, r0 + break; + default: + error("Unknown unary op %d\n", op); + break; + } } virtual void pushR0() { @@ -575,28 +626,38 @@ class Compiler : public ErrorSink { LOG_STACK("pushR0: %d\n", mStackUse); } - virtual void popR1() { - LOG_API("popR1();\n"); + virtual void storeR0ToTOS(Type* pPointerType) { + LOG_API("storeR0ToTOS(%d);\n", isInt); + assert(pPointerType->tag == TY_POINTER); o4(0xE8BD0002); // ldmfd sp!,{r1} mStackUse -= 4; - LOG_STACK("popR1: %d\n", mStackUse); - } - - virtual void storeR0ToR1(bool isInt) { - LOG_API("storeR0ToR1(%d);\n", isInt); - if (isInt) { - o4(0xE5810000); // str r0, [r1] - } else { - o4(0xE5C10000); // strb r0, [r1] + switch (pPointerType->pHead->tag) { + case TY_INT: + o4(0xE5810000); // str r0, [r1] + break; + case TY_CHAR: + o4(0xE5C10000); // strb r0, [r1] + break; + default: + assert(false); + break; } } - virtual void loadR0FromR0(bool isInt) { - LOG_API("loadR0FromR0(%d);\n", isInt); - if (isInt) - o4(0xE5900000); // ldr r0, [r0] - else - o4(0xE5D00000); // ldrb r0, [r0] + virtual void loadR0FromR0(Type* pPointerType) { + LOG_API("loadR0FromR0(%d);\n", pPointerType); + assert(pPointerType->tag == TY_POINTER); + switch (pPointerType->pHead->tag) { + case TY_INT: + o4(0xE5900000); // ldr r0, [r0] + break; + case TY_CHAR: + o4(0xE5D00000); // ldrb r0, [r0] + break; + default: + assert(false); + break; + } } virtual void leaR0(int ea) { @@ -834,6 +895,37 @@ class Compiler : public ErrorSink { return 0; } + /** + * Stack alignment (in bytes) for this type of data + */ + virtual size_t stackAlignment(Type* pType){ + switch(pType->tag) { + case TY_DOUBLE: + return 8; + default: + return 4; + } + } + + /** + * Array element alignment (in bytes) for this type of data. + */ + virtual size_t sizeOf(Type* pType){ + switch(pType->tag) { + case TY_INT: + return 4; + case TY_CHAR: + return 1; + default: + return 0; + case TY_FLOAT: + return 4; + case TY_DOUBLE: + return 8; + case TY_POINTER: + return 4; + } + } private: static FILE* disasmOut; @@ -937,6 +1029,7 @@ class Compiler : public ErrorSink { virtual void gcmp(int op) { int t = decodeOp(op); + o(0x59); /* pop %ecx */ o(0xc139); /* cmp %eax,%ecx */ li(0); o(0x0f); /* setxx %al */ @@ -945,32 +1038,60 @@ class Compiler : public ErrorSink { } virtual void genOp(int op) { + o(0x59); /* pop %ecx */ o(decodeOp(op)); if (op == OP_MOD) o(0x92); /* xchg %edx, %eax */ } - virtual void clearR1() { + virtual void gUnaryCmp(int op) { + oad(0xb9, 0); /* movl $0, %ecx */ + int t = decodeOp(op); + o(0xc139); /* cmp %eax,%ecx */ + li(0); + o(0x0f); /* setxx %al */ + o(t + 0x90); + o(0xc0); + } + + virtual void genUnaryOp(int op) { oad(0xb9, 0); /* movl $0, %ecx */ + o(decodeOp(op)); } virtual void pushR0() { o(0x50); /* push %eax */ } - virtual void popR1() { + virtual void storeR0ToTOS(Type* pPointerType) { + assert(pPointerType->tag == TY_POINTER); o(0x59); /* pop %ecx */ + switch (pPointerType->pHead->tag) { + case TY_INT: + o(0x0189); /* movl %eax/%al, (%ecx) */ + break; + case TY_CHAR: + o(0x0188); /* movl %eax/%al, (%ecx) */ + break; + default: + assert(false); + break; + } } - virtual void storeR0ToR1(bool isInt) { - o(0x0188 + isInt); /* movl %eax/%al, (%ecx) */ - } - - virtual void loadR0FromR0(bool isInt) { - if (isInt) - o(0x8b); /* mov (%eax), %eax */ - else - o(0xbe0f); /* movsbl (%eax), %eax */ + virtual void loadR0FromR0(Type* pPointerType) { + assert(pPointerType->tag == TY_POINTER); + switch (pPointerType->pHead->tag) { + case TY_INT: + o(0x8b); /* mov (%eax), %eax */ + break; + case TY_CHAR: + o(0xbe0f); /* movsbl (%eax), %eax */ + break; + default: + assert(false); + break; + } ob(0); /* add zero in code */ } @@ -1055,6 +1176,38 @@ class Compiler : public ErrorSink { return err; } + /** + * Stack alignment (in bytes) for this type of data + */ + virtual size_t stackAlignment(Type* pType){ + switch(pType->tag) { + case TY_DOUBLE: + return 8; + default: + return 4; + } + } + + /** + * Array element alignment (in bytes) for this type of data. + */ + virtual size_t sizeOf(Type* pType){ + switch(pType->tag) { + case TY_INT: + return 4; + case TY_CHAR: + return 1; + default: + return 0; + case TY_FLOAT: + return 4; + case TY_DOUBLE: + return 8; + case TY_POINTER: + return 4; + } + } + private: /** Output 1 to 4 bytes. @@ -1166,9 +1319,15 @@ class Compiler : public ErrorSink { mpBase->genOp(op); } - virtual void clearR1() { - fprintf(stderr, "clearR1()\n"); - mpBase->clearR1(); + + virtual void gUnaryCmp(int op) { + fprintf(stderr, "gUnaryCmp(%d)\n", op); + mpBase->gUnaryCmp(op); + } + + virtual void genUnaryOp(int op) { + fprintf(stderr, "genUnaryOp(%d)\n", op); + mpBase->genUnaryOp(op); } virtual void pushR0() { @@ -1176,19 +1335,14 @@ class Compiler : public ErrorSink { mpBase->pushR0(); } - virtual void popR1() { - fprintf(stderr, "popR1()\n"); - mpBase->popR1(); + virtual void storeR0ToTOS(Type* pPointerType) { + fprintf(stderr, "storeR0ToTOS(%d)\n", pPointerType); + mpBase->storeR0ToTOS(pPointerType); } - virtual void storeR0ToR1(bool isInt) { - fprintf(stderr, "storeR0ToR1(%d)\n", isInt); - mpBase->storeR0ToR1(isInt); - } - - virtual void loadR0FromR0(bool isInt) { - fprintf(stderr, "loadR0FromR0(%d)\n", isInt); - mpBase->loadR0FromR0(isInt); + virtual void loadR0FromR0(Type* pPointerType) { + fprintf(stderr, "loadR0FromR0(%d)\n", pPointerType); + mpBase->loadR0FromR0(pPointerType); } virtual void leaR0(int ea) { @@ -1262,6 +1416,20 @@ class Compiler : public ErrorSink { fprintf(stderr, "finishCompile() = %d\n", result); return result; } + + /** + * Stack alignment (in bytes) for this type of data + */ + virtual size_t stackAlignment(Type* pType){ + return mpBase->stackAlignment(pType); + } + + /** + * Array element alignment (in bytes) for this type of data. + */ + virtual size_t sizeOf(Type* pType){ + return mpBase->sizeOf(pType); + } }; #endif // PROVIDE_TRACE_CODEGEN @@ -1760,8 +1928,6 @@ class Compiler : public ErrorSink { int oldCh; }; - struct Type; - struct VariableInfo { void* pAddress; void* pForward; // For a forward direction, linked list of data to fix up @@ -1876,9 +2042,9 @@ class Compiler : public ErrorSink { SymbolStack mLocals; // Prebuilt types, makes things slightly faster. - Type* mkpInt; - Type* mkpChar; - Type* mkpVoid; + Type* mkpInt; // int + Type* mkpChar; // char + Type* mkpVoid; // void Type* mkpFloat; Type* mkpDouble; Type* mkpIntPtr; @@ -2381,11 +2547,10 @@ class Compiler : public ErrorSink { } else if (c == 2) { /* -, +, !, ~ */ unary(false); - pGen->clearR1(); if (t == '!') - pGen->gcmp(a); + pGen->gUnaryCmp(a); else - pGen->genOp(a); + pGen->genUnaryOp(a); } else if (t == '(') { expr(); skip(')'); @@ -2415,10 +2580,9 @@ class Compiler : public ErrorSink { if (accept('=')) { pGen->pushR0(); expr(); - pGen->popR1(); - pGen->storeR0ToR1(t == TOK_INT); + pGen->storeR0ToTOS(pCast); } else if (t) { - pGen->loadR0FromR0(t == TOK_INT); + pGen->loadR0FromR0(pCast); } // Else we fall through to the function call below, with // t == 0 to trigger an indirect function call. Hack! @@ -2515,7 +2679,6 @@ class Compiler : public ErrorSink { } else { pGen->pushR0(); binaryOp(level); - pGen->popR1(); if ((level == 4) | (level == 5)) { pGen->gcmp(t); @@ -2958,6 +3121,7 @@ class Compiler : public ErrorSink { } int variableAddress = 0; addLocalSymbol(pDecl); + loc = loc + pGen->sizeOf(pDecl); loc = loc + 4; variableAddress = -loc; VI(pDecl->id)->pAddress = (void*) variableAddress; |
