Code generator cleanup
Factor ARM integer binary operation setup code into a function.
Don't pass redundant pType information into loadR0FromR0, storeR0ToTOS,
gcmp, gUnaryCmp, li
Separate inc/dec from variable loading. Generates worse code, but now
we handle pointer inc/dec and char inc/dec.
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index e097608..bf48490 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -282,6 +282,11 @@
}
}
+ /* Give the code generator some utility types so it can
+ * use its own types as needed for the results of some
+ * operations like gcmp.
+ */
+
void setTypes(Type* pInt) {
mkpInt = pInt;
}
@@ -312,7 +317,7 @@
int localVariableSize) = 0;
/* load immediate value to R0 */
- virtual void li(int i, Type* pType) = 0;
+ virtual void li(int i) = 0;
/* Load floating point value from global address. */
virtual void loadFloat(int address, Type* pType) = 0;
@@ -333,7 +338,7 @@
* Pops TOS.
* op specifies the comparison.
*/
- virtual void gcmp(int op, Type* pResultType) = 0;
+ virtual void gcmp(int op) = 0;
/* Perform the arithmetic op specified by op. TOS is the
* left argument, R0 is the right argument.
@@ -344,7 +349,7 @@
/* Compare 0 against R0, and store the boolean result in R0.
* op specifies the comparison.
*/
- virtual void gUnaryCmp(int op, Type* pResultType) = 0;
+ virtual void gUnaryCmp(int op) = 0;
/* Perform the arithmetic op specified by op. 0 is the
* left argument, R0 is the right argument.
@@ -355,16 +360,18 @@
*/
virtual void pushR0() = 0;
+ /* Pop R0 from the stack.
+ */
+ virtual void popR0() = 0;
+
/* 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 storeR0ToTOS(Type* pPointerType) = 0;
+ virtual void storeR0ToTOS() = 0;
/* Load R0 from the address stored in R0.
- * pPointerType is the type of the pointer (of the input R0).
*/
- virtual void loadR0FromR0(Type* pPointerType) = 0;
+ virtual void loadR0FromR0() = 0;
/* Load the absolute address of a variable to R0.
* If ea <= LOCAL, then this is a local variable, or an
@@ -384,11 +391,8 @@
* If ea <= LOCAL, then this is a local variable, or an
* argument, addressed relative to FP.
* else it is an absolute global address.
- * If isIncDec is true, then the stored variable's value
- * should be post-incremented or post-decremented, based
- * on the value of op.
*/
- virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) = 0;
+ virtual void loadR0(int ea, Type* pType) = 0;
/**
* Convert R0 to the given type.
@@ -636,9 +640,9 @@
}
/* load immediate value */
- virtual void li(int t, Type* pType) {
+ virtual void li(int t) {
liReg(t, 0);
- setR0Type(pType);
+ setR0Type(mkpInt);
}
virtual void loadFloat(int address, Type* pType) {
@@ -685,14 +689,13 @@
return o4(branch | encodeAddress(t));
}
- virtual void gcmp(int op, Type* pResultType) {
+ virtual void gcmp(int op) {
Type* pR0Type = getR0Type();
Type* pTOSType = getTOSType();
TypeTag tagR0 = collapseType(pR0Type->tag);
TypeTag tagTOS = collapseType(pTOSType->tag);
if (tagR0 == TY_INT && tagTOS == TY_INT) {
- o4(0xE8BD0002); // ldmfd sp!,{r1}
- mStackUse -= 4;
+ setupIntPtrArgs();
o4(0xE1510000); // cmp r1, r1
switch(op) {
case OP_EQUALS:
@@ -723,7 +726,6 @@
error("Unknown comparison op %d", op);
break;
}
- popType();
} else if (tagR0 == TY_DOUBLE || tagTOS == TY_DOUBLE) {
setupDoubleArgs();
switch(op) {
@@ -775,7 +777,7 @@
break;
}
}
- setR0Type(pResultType);
+ setR0Type(mkpInt);
}
virtual void genOp(int op) {
@@ -786,6 +788,7 @@
bool isFloatR0 = isFloatTag(tagR0);
bool isFloatTOS = isFloatTag(tagTOS);
if (!isFloatR0 && !isFloatTOS) {
+ setupIntPtrArgs();
bool isPtrR0 = tagR0 == TY_POINTER;
bool isPtrTOS = tagTOS == TY_POINTER;
if (isPtrR0 || isPtrTOS) {
@@ -796,14 +799,12 @@
if (! typeEqual(pR0Type, pTOSType)) {
error("Incompatible pointer types for subtraction.");
}
- o4(0xE8BD0002); // ldmfd sp!,{r1}
o4(0xE0410000); // sub r0,r1,r0
- popType();
setR0Type(mkpInt);
int size = sizeOf(pR0Type->pHead);
if (size != 1) {
pushR0();
- li(size, mkpInt);
+ li(size);
// TODO: Optimize for power-of-two.
genOp(OP_DIV);
}
@@ -812,7 +813,6 @@
error("Unsupported pointer-scalar operation %d", op);
}
Type* pPtrType = isPtrR0 ? pR0Type : pTOSType;
- o4(0xE8BD0002); // ldmfd sp!,{r1}
int size = sizeOf(pPtrType->pHead);
if (size != 1) {
// TODO: Optimize for power-of-two.
@@ -831,12 +831,9 @@
o4(0xE0410000); // sub r0,r1,r0
break;
}
- popType();
setR0Type(pPtrType);
}
} else {
- o4(0xE8BD0002); // ldmfd sp!,{r1}
- mStackUse -= 4;
switch(op) {
case OP_MUL:
o4(0x0E0000091); // mul r0,r1,r0
@@ -875,7 +872,6 @@
error("Unimplemented op %d\n", op);
break;
}
- popType();
}
} else {
Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType;
@@ -922,7 +918,7 @@
}
}
- virtual void gUnaryCmp(int op, Type* pResultType) {
+ virtual void gUnaryCmp(int op) {
if (op != OP_LOGICAL_NOT) {
error("Unknown unary cmp %d", op);
} else {
@@ -946,7 +942,7 @@
break;
}
}
- setR0Type(pResultType);
+ setR0Type(mkpInt);
}
virtual void genUnaryOp(int op) {
@@ -1005,7 +1001,28 @@
LOG_STACK("pushR0: %d\n", mStackUse);
}
- virtual void storeR0ToTOS(Type* pPointerType) {
+ virtual void popR0() {
+ Type* pTOSType = getTOSType();
+ switch (collapseType(pTOSType->tag)){
+ case TY_INT:
+ case TY_FLOAT:
+ o4(0xE8BD0001); // ldmfd sp!,{r0}
+ mStackUse -= 4;
+ break;
+ case TY_DOUBLE:
+ o4(0xE8BD0003); // ldmfd sp!,{r0, r1} // Restore R0
+ mStackUse -= 8;
+ break;
+ default:
+ error("Can't pop this type.");
+ break;
+ }
+ popType();
+ LOG_STACK("popR0: %d\n", mStackUse);
+ }
+
+ virtual void storeR0ToTOS() {
+ Type* pPointerType = getTOSType();
assert(pPointerType->tag == TY_POINTER);
o4(0xE8BD0004); // ldmfd sp!,{r2}
popType();
@@ -1027,7 +1044,8 @@
}
}
- virtual void loadR0FromR0(Type* pPointerType) {
+ virtual void loadR0FromR0() {
+ Type* pPointerType = getR0Type();
assert(pPointerType->tag == TY_POINTER);
switch (pPointerType->pHead->tag) {
case TY_INT:
@@ -1149,7 +1167,7 @@
}
}
- virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) {
+ virtual void loadR0(int ea, Type* pType) {
TypeTag tag = pType->tag;
switch (tag) {
case TY_CHAR:
@@ -1170,10 +1188,6 @@
o4(ea); // .L1: .word ea
o4(0xE5D20000); // .L99: ldrb r0, [r2]
}
-
- if (isIncDec) {
- error("inc/dec not implemented for char.");
- }
break;
case TY_POINTER:
case TY_INT:
@@ -1195,37 +1209,6 @@
o4(ea); // .L1: .word ea
o4(0xE5920000); // .L99: ldr r0, [r2]
}
-
- if (isIncDec) {
- if (tag == TY_INT) {
- switch (op) {
- case OP_INCREMENT:
- o4(0xE2801001); // add r1, r0, #1
- break;
- case OP_DECREMENT:
- o4(0xE2401001); // sub r1, r0, #1
- break;
- default:
- error("unknown opcode: %d", op);
- }
- if (ea < LOCAL) {
- // Local, fp relative
- // Don't need range check, was already checked above
- if (ea < 0) {
- o4(0xE50B1000 | (0xfff & (-ea))); // str r1, [fp,#-ea]
- } else {
- o4(0xE58B1000 | (0xfff & ea)); // str r1, [fp,#ea]
- }
- } else{
- // Global, absolute
- // r2 is already set up from before.
- o4(0xE5821000); // str r1, [r2]
- }
- }
- else {
- error("inc/dec not implemented for float.");
- }
- }
break;
case TY_DOUBLE:
if ((ea & 0x7) != 0) {
@@ -1563,6 +1546,12 @@
return reg;
}
+ void setupIntPtrArgs() {
+ o4(0xE8BD0002); // ldmfd sp!,{r1}
+ mStackUse -= 4;
+ popType();
+ }
+
/* Pop TOS to R1
* Make sure both R0 and TOS are floats. (Could be ints)
* We know that at least one of R0 and TOS is already a float
@@ -1837,9 +1826,9 @@
}
/* load immediate value */
- virtual void li(int i, Type* pType) {
+ virtual void li(int i) {
oad(0xb8, i); /* mov $xx, %eax */
- setR0Type(pType);
+ setR0Type(mkpInt);
}
virtual void loadFloat(int address, Type* pType) {
@@ -1879,7 +1868,7 @@
return psym(0x84 + l, t);
}
- virtual void gcmp(int op, Type* pResultType) {
+ virtual void gcmp(int op) {
Type* pR0Type = getR0Type();
Type* pTOSType = getTOSType();
TypeTag tagR0 = pR0Type->tag;
@@ -1890,7 +1879,7 @@
int t = decodeOp(op);
o(0x59); /* pop %ecx */
o(0xc139); /* cmp %eax,%ecx */
- li(0, NULL);
+ li(0);
o(0x0f); /* setxx %al */
o(t + 0x90);
o(0xc0);
@@ -1945,7 +1934,7 @@
}
o(0xc0b60f); // movzbl %al, %eax
}
- setR0Type(pResultType);
+ setR0Type(mkpInt);
}
virtual void genOp(int op) {
@@ -1973,7 +1962,7 @@
int size = sizeOf(pR0Type->pHead);
if (size != 1) {
pushR0();
- li(size, mkpInt);
+ li(size);
// TODO: Optimize for power-of-two.
genOp(OP_DIV);
}
@@ -2028,7 +2017,7 @@
}
}
- virtual void gUnaryCmp(int op, Type* pResultType) {
+ virtual void gUnaryCmp(int op) {
if (op != OP_LOGICAL_NOT) {
error("Unknown unary cmp %d", op);
} else {
@@ -2039,7 +2028,7 @@
oad(0xb9, 0); /* movl $0, %ecx */
int t = decodeOp(op);
o(0xc139); /* cmp %eax,%ecx */
- li(0, NULL);
+ li(0);
o(0x0f); /* setxx %al */
o(t + 0x90);
o(0xc0);
@@ -2062,7 +2051,7 @@
break;
}
}
- setR0Type(pResultType);
+ setR0Type(mkpInt);
}
virtual void genUnaryOp(int op) {
@@ -2116,7 +2105,31 @@
pushType();
}
- virtual void storeR0ToTOS(Type* pPointerType) {
+ virtual void popR0() {
+ Type* pR0Type = getR0Type();
+ TypeTag r0ct = collapseType(pR0Type->tag);
+ switch(r0ct) {
+ case TY_INT:
+ o(0x58); /* popl %eax */
+ break;
+ case TY_FLOAT:
+ o(0x2404d9); // flds (%esp)
+ o(0x58); /* popl %eax */
+ break;
+ case TY_DOUBLE:
+ o(0x2404dd); // fldl (%esp)
+ o(0x58); /* popl %eax */
+ o(0x58); /* popl %eax */
+ break;
+ default:
+ error("pushR0 unsupported type %d", r0ct);
+ break;
+ }
+ popType();
+ }
+
+ virtual void storeR0ToTOS() {
+ Type* pPointerType = getTOSType();
assert(pPointerType->tag == TY_POINTER);
Type* pTargetType = pPointerType->pHead;
convertR0(pTargetType);
@@ -2141,7 +2154,8 @@
}
}
- virtual void loadR0FromR0(Type* pPointerType) {
+ virtual void loadR0FromR0() {
+ Type* pPointerType = getR0Type();
assert(pPointerType->tag == TY_POINTER);
switch (pPointerType->pHead->tag) {
case TY_INT:
@@ -2204,7 +2218,7 @@
}
}
- virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) {
+ virtual void loadR0(int ea, Type* pType) {
TypeTag tag = pType->tag;
switch (tag) {
case TY_CHAR:
@@ -2213,22 +2227,10 @@
} else {
oad(0x85BE0F, ea); // movsbl ea(%ebp),%eax
}
- if (isIncDec) {
- error("inc/dec not implemented for char.");
- }
break;
case TY_INT:
case TY_POINTER:
- if (tag == TY_CHAR) {
- } else {
- gmov(8, ea); /* mov EA, %eax */
- }
- if (isIncDec) {
- /* Implement post-increment or post decrement.
- */
- gmov(0, ea); /* 83 ADD */
- o(decodeOp(op));
- }
+ gmov(8, ea); /* mov EA, %eax */
break;
case TY_FLOAT:
if (ea < -LOCAL || ea > LOCAL) {
@@ -2236,9 +2238,6 @@
} else {
oad(0x85d9, ea); // flds ea(%ebp)
}
- if (isIncDec) {
- error("inc/dec not implemented for float.");
- }
break;
case TY_DOUBLE:
if (ea < -LOCAL || ea > LOCAL) {
@@ -2246,9 +2245,6 @@
} else {
oad(0x85dd, ea); // fldl ea(%ebp)
}
- if (isIncDec) {
- error("inc/dec not implemented for double.");
- }
break;
default:
error("Unable to load type %d", tag);
@@ -2535,9 +2531,9 @@
}
/* load immediate value */
- virtual void li(int t, Type* pType) {
+ virtual void li(int t) {
fprintf(stderr, "li(%d)\n", t);
- mpBase->li(t, pType);
+ mpBase->li(t);
}
virtual void loadFloat(int address, Type* pType) {
@@ -2558,9 +2554,9 @@
return result;
}
- virtual void gcmp(int op, Type* pResultType) {
- fprintf(stderr, "gcmp(%d, pResultType)\n", op);
- mpBase->gcmp(op, pResultType);
+ virtual void gcmp(int op) {
+ fprintf(stderr, "gcmp(%d)\n", op);
+ mpBase->gcmp(op);
}
virtual void genOp(int op) {
@@ -2569,9 +2565,9 @@
}
- virtual void gUnaryCmp(int op, Type* pResultType) {
- fprintf(stderr, "gUnaryCmp(%d, pResultType)\n", op);
- mpBase->gUnaryCmp(op, pResultType);
+ virtual void gUnaryCmp(int op) {
+ fprintf(stderr, "gUnaryCmp(%d)\n", op);
+ mpBase->gUnaryCmp(op);
}
virtual void genUnaryOp(int op) {
@@ -2584,14 +2580,19 @@
mpBase->pushR0();
}
- virtual void storeR0ToTOS(Type* pPointerType) {
- fprintf(stderr, "storeR0ToTOS(%d)\n", pPointerType->pHead->tag);
- mpBase->storeR0ToTOS(pPointerType);
+ virtual void popR0() {
+ fprintf(stderr, "popR0()\n");
+ mpBase->popR0();
}
- virtual void loadR0FromR0(Type* pPointerType) {
- fprintf(stderr, "loadR0FromR0(%d)\n", pPointerType->pHead->tag);
- mpBase->loadR0FromR0(pPointerType);
+ virtual void storeR0ToTOS() {
+ fprintf(stderr, "storeR0ToTOS()\n");
+ mpBase->storeR0ToTOS();
+ }
+
+ virtual void loadR0FromR0() {
+ fprintf(stderr, "loadR0FromR0()\n");
+ mpBase->loadR0FromR0();
}
virtual void leaR0(int ea, Type* pPointerType) {
@@ -2604,9 +2605,9 @@
mpBase->storeR0(ea, pType);
}
- virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) {
- fprintf(stderr, "loadR0(%d, %d, %d, pType)\n", ea, isIncDec, op);
- mpBase->loadR0(ea, isIncDec, op, pType);
+ virtual void loadR0(int ea, Type* pType) {
+ fprintf(stderr, "loadR0(%d, pType)\n", ea);
+ mpBase->loadR0(ea, pType);
}
virtual void convertR0(Type* pType){
@@ -3814,7 +3815,7 @@
bool acceptStringLiteral() {
if (tok == '"') {
- pGen->li((int) glo, mkpCharPtr);
+ pGen->leaR0((int) glo, mkpCharPtr);
// This while loop merges multiple adjacent string constants.
while (tok == '"') {
while (ch != '"' && ch != EOF) {
@@ -3869,7 +3870,7 @@
t = tok;
next();
if (t == TOK_NUM) {
- pGen->li(a, mkpInt);
+ pGen->li(a);
} else if (t == TOK_NUM_FLOAT) {
// Align to 4-byte boundary
glo = (char*) (((intptr_t) glo + 3) & -4);
@@ -3886,7 +3887,7 @@
/* -, +, !, ~ */
unary(false);
if (t == '!')
- pGen->gUnaryCmp(a, mkpInt);
+ pGen->gUnaryCmp(a);
else if (t == '+') {
// ignore unary plus.
} else {
@@ -3917,9 +3918,9 @@
if (accept('=')) {
pGen->pushR0();
expr();
- pGen->storeR0ToTOS(pR0Type);
+ pGen->storeR0ToTOS();
} else if (t) {
- pGen->loadR0FromR0(pR0Type);
+ pGen->loadR0FromR0();
}
}
// Else we fall through to the function call below, with
@@ -3965,8 +3966,14 @@
error("Undeclared variable %s\n", nameof(t));
}
}
- pGen->loadR0(n, tokl == 11, tokc, pVI->pType);
+ // load a variable
+ pGen->loadR0(n, pVI->pType);
if (tokl == 11) {
+ // post inc / post dec
+ pGen->pushR0();
+ impInc(tokc);
+ pGen->storeR0(n, pVI->pType);
+ pGen->popR0();
next();
}
}
@@ -4037,6 +4044,28 @@
}
}
+ /* Increment / decrement R0 */
+
+ void impInc(int op) {
+ Type* pType = pGen->getR0Type();
+ int lit = 1;
+ if (op == OP_DECREMENT) {
+ lit = -1;
+ }
+ switch (pType->tag) {
+ case TY_INT:
+ case TY_CHAR:
+ case TY_POINTER:
+ pGen->pushR0();
+ pGen->li(lit);
+ pGen->genOp(OP_PLUS);
+ break;
+ default:
+ error("++/-- illegal for this type.");
+ break;
+ }
+ }
+
/* Recursive descent parser for binary operations.
*/
void binaryOp(int level) {
@@ -4061,10 +4090,10 @@
if (pGen->getR0Type() == NULL) {
// We failed to parse a right-hand argument.
// Push a dummy value so we don't fail
- pGen->li(0, mkpInt);
+ pGen->li(0);
}
if ((level == 4) | (level == 5)) {
- pGen->gcmp(t, mkpInt);
+ pGen->gcmp(t);
} else {
pGen->genOp(t);
}
@@ -4073,10 +4102,10 @@
/* && and || output code generation */
if (a && level > 8) {
a = pGen->gtst(t == OP_LOGICAL_OR, a);
- pGen->li(t != OP_LOGICAL_OR, mkpInt);
+ pGen->li(t != OP_LOGICAL_OR);
pGen->gjmp(5); /* jmp $ + 5 (sizeof li, FIXME for ARM) */
pGen->gsym(a);
- pGen->li(t == OP_LOGICAL_OR, mkpInt);
+ pGen->li(t == OP_LOGICAL_OR);
}
}
}