Implement inc/dec in a more lval-friendly way.

This commit is contained in:
Jack Palevich 2009-07-29 10:28:18 -07:00
parent 7fcdf1c5f8
commit ddf7c9c141
3 changed files with 125 additions and 32 deletions

View File

@ -356,11 +356,15 @@ class Compiler : public ErrorSink {
*/
virtual void genUnaryOp(int op) = 0;
/* Push R0 onto the stack.
/* Push R0 onto the stack. (Also known as "dup" for duplicate.)
*/
virtual void pushR0() = 0;
/* Pop R0 from the stack.
/* Turn R0, TOS into R0 TOS R0 */
virtual void over() = 0;
/* Pop R0 from the stack. (Also known as "drop")
*/
virtual void popR0() = 0;
@ -490,18 +494,22 @@ class Compiler : public ErrorSink {
*/
virtual size_t stackSizeOf(Type* pType) = 0;
Type* getR0Type() {
virtual Type* getR0Type() {
return mExpressionStack.back().pType;
}
ExpressionType getR0ExpressionType() {
virtual ExpressionType getR0ExpressionType() {
return mExpressionStack.back().et;
}
void setR0ExpressionType(ExpressionType et) {
virtual void setR0ExpressionType(ExpressionType et) {
mExpressionStack.back().et = et;
}
virtual size_t getExpressionStackDepth() {
return mExpressionStack.size();
}
protected:
/*
* Output a byte. Handles all values, 0..ff.
@ -541,6 +549,7 @@ class Compiler : public ErrorSink {
}
void setR0Type(Type* pType) {
assert(pType != NULL);
mExpressionStack.back().pType = pType;
}
@ -557,6 +566,15 @@ class Compiler : public ErrorSink {
}
void overType() {
size_t size = mExpressionStack.size();
if (size >= 2) {
mExpressionStack.push_back(mExpressionStack.back());
mExpressionStack[size-1] = mExpressionStack[size-2];
mExpressionStack[size-2] = mExpressionStack[size];
}
}
void popType() {
mExpressionStack.pop_back();
}
@ -1014,6 +1032,24 @@ class Compiler : public ErrorSink {
LOG_STACK("pushR0: %d\n", mStackUse);
}
virtual void over() {
// We know it's only used for int-ptr ops (++/--)
Type* pR0Type = getR0Type();
TypeTag r0ct = collapseType(pR0Type->tag);
Type* pTOSType = getTOSType();
TypeTag tosct = collapseType(pTOSType->tag);
assert (r0ct == TY_INT && tosct == TY_INT);
o4(0xE8BD0002); // ldmfd sp!,{r1}
o4(0xE92D0001); // stmfd sp!,{r0}
o4(0xE92D0002); // stmfd sp!,{r1}
overType();
mStackUse += 4;
}
virtual void popR0() {
Type* pTOSType = getTOSType();
switch (collapseType(pTOSType->tag)){
@ -2129,6 +2165,24 @@ class Compiler : public ErrorSink {
pushType();
}
virtual void over() {
// We know it's only used for int-ptr ops (++/--)
Type* pR0Type = getR0Type();
TypeTag r0ct = collapseType(pR0Type->tag);
Type* pTOSType = getTOSType();
TypeTag tosct = collapseType(pTOSType->tag);
assert (r0ct == TY_INT && tosct == TY_INT);
o(0x59); /* pop %ecx */
o(0x50); /* push %eax */
o(0x51); /* push %ecx */
overType();
}
virtual void popR0() {
Type* pR0Type = getR0Type();
TypeTag r0ct = collapseType(pR0Type->tag);
@ -2146,7 +2200,7 @@ class Compiler : public ErrorSink {
o(0x58); /* popl %eax */
break;
default:
error("pushR0 unsupported type %d", r0ct);
error("popR0 unsupported type %d", r0ct);
break;
}
popType();
@ -2613,6 +2667,11 @@ class Compiler : public ErrorSink {
mpBase->pushR0();
}
virtual void over() {
fprintf(stderr, "over()\n");
mpBase->over();
}
virtual void popR0() {
fprintf(stderr, "popR0()\n");
mpBase->popR0();
@ -2721,14 +2780,30 @@ class Compiler : public ErrorSink {
}
virtual size_t stackAlignmentOf(Type* pType) {
return mpBase->stackAlignmentOf(pType);
}
virtual size_t stackSizeOf(Type* pType) {
return mpBase->stackSizeOf(pType);
}
virtual Type* getR0Type() {
return mpBase->getR0Type();
}
virtual ExpressionType getR0ExpressionType() {
return mpBase->getR0ExpressionType();
}
virtual void setR0ExpressionType(ExpressionType et) {
mpBase->setR0ExpressionType(et);
}
virtual size_t getExpressionStackDepth() {
return mpBase->getExpressionStackDepth();
}
};
#endif // PROVIDE_TRACE_CODEGEN
@ -4001,14 +4076,35 @@ class Compiler : public ErrorSink {
}
}
// load a variable
pGen->loadR0(n, pVI->pType);
if (tokl == 11) {
// post inc / post dec
pGen->leaR0(n, createPtrType(pVI->pType));
pGen->pushR0();
impInc(tokc);
pGen->storeR0(n, pVI->pType);
pGen->loadR0FromR0();
pGen->over();
int lit = 1;
if (tokc == OP_DECREMENT) {
lit = -1;
}
switch (pVI->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;
}
pGen->storeR0ToTOS();
pGen->popR0();
next();
} else {
pGen->loadR0(n, pVI->pType);
}
}
}
@ -4078,28 +4174,6 @@ class Compiler : public ErrorSink {
}
}
/* 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) {

10
libacc/tests/data/inc.c Normal file
View File

@ -0,0 +1,10 @@
// Check integer operations
int main() {
int a = 0;
printf("%d\n", a++);
printf("%d\n", a++);
printf("%d\n", a--);
printf("%d\n", a--);
return a;
}

View File

@ -287,6 +287,15 @@ result: 10""", """""")
self.compileCheck(["-R", "data/floatdouble.c"], """Executing compiled code:
result: 0""", """0.002 0.1 10""")
def testIncDec(self):
self.compileCheck(["-R", "data/inc.c"], """Executing compiled code:
0
1
2
1
result: 0
""","""""")
def testIops(self):
self.compileCheck(["-R", "data/iops.c"], """Executing compiled code:
result: 0""", """Literals: 1 -1