Loading libacc/acc.cpp +153 −124 Original line number Diff line number Diff line Loading @@ -282,6 +282,11 @@ class Compiler : public ErrorSink { } } /* 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; } Loading Loading @@ -312,7 +317,7 @@ class Compiler : public ErrorSink { 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; Loading @@ -333,7 +338,7 @@ class Compiler : public ErrorSink { * 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. Loading @@ -344,7 +349,7 @@ class Compiler : public ErrorSink { /* 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. Loading @@ -355,16 +360,18 @@ class Compiler : public ErrorSink { */ 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 Loading @@ -384,11 +391,8 @@ class Compiler : public ErrorSink { * 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. Loading Loading @@ -636,9 +640,9 @@ class Compiler : public ErrorSink { } /* 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) { Loading Loading @@ -685,14 +689,13 @@ class Compiler : public ErrorSink { 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: Loading Loading @@ -723,7 +726,6 @@ class Compiler : public ErrorSink { error("Unknown comparison op %d", op); break; } popType(); } else if (tagR0 == TY_DOUBLE || tagTOS == TY_DOUBLE) { setupDoubleArgs(); switch(op) { Loading Loading @@ -775,7 +777,7 @@ class Compiler : public ErrorSink { break; } } setR0Type(pResultType); setR0Type(mkpInt); } virtual void genOp(int op) { Loading @@ -786,6 +788,7 @@ class Compiler : public ErrorSink { 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) { Loading @@ -796,14 +799,12 @@ class Compiler : public ErrorSink { 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); } Loading @@ -812,7 +813,6 @@ class Compiler : public ErrorSink { 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. Loading @@ -831,12 +831,9 @@ class Compiler : public ErrorSink { 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 Loading Loading @@ -875,7 +872,6 @@ class Compiler : public ErrorSink { error("Unimplemented op %d\n", op); break; } popType(); } } else { Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType; Loading Loading @@ -922,7 +918,7 @@ class Compiler : public ErrorSink { } } virtual void gUnaryCmp(int op, Type* pResultType) { virtual void gUnaryCmp(int op) { if (op != OP_LOGICAL_NOT) { error("Unknown unary cmp %d", op); } else { Loading @@ -946,7 +942,7 @@ class Compiler : public ErrorSink { break; } } setR0Type(pResultType); setR0Type(mkpInt); } virtual void genUnaryOp(int op) { Loading Loading @@ -1005,7 +1001,28 @@ class Compiler : public ErrorSink { 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(); Loading @@ -1027,7 +1044,8 @@ class Compiler : public ErrorSink { } } virtual void loadR0FromR0(Type* pPointerType) { virtual void loadR0FromR0() { Type* pPointerType = getR0Type(); assert(pPointerType->tag == TY_POINTER); switch (pPointerType->pHead->tag) { case TY_INT: Loading Loading @@ -1149,7 +1167,7 @@ class Compiler : public ErrorSink { } } 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: Loading @@ -1170,10 +1188,6 @@ class Compiler : public ErrorSink { 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: Loading @@ -1195,37 +1209,6 @@ class Compiler : public ErrorSink { 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) { Loading Loading @@ -1563,6 +1546,12 @@ class Compiler : public ErrorSink { 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 Loading Loading @@ -1837,9 +1826,9 @@ class Compiler : public ErrorSink { } /* 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) { Loading Loading @@ -1879,7 +1868,7 @@ class Compiler : public ErrorSink { 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; Loading @@ -1890,7 +1879,7 @@ class Compiler : public ErrorSink { 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); Loading Loading @@ -1945,7 +1934,7 @@ class Compiler : public ErrorSink { } o(0xc0b60f); // movzbl %al, %eax } setR0Type(pResultType); setR0Type(mkpInt); } virtual void genOp(int op) { Loading Loading @@ -1973,7 +1962,7 @@ class Compiler : public ErrorSink { int size = sizeOf(pR0Type->pHead); if (size != 1) { pushR0(); li(size, mkpInt); li(size); // TODO: Optimize for power-of-two. genOp(OP_DIV); } Loading Loading @@ -2028,7 +2017,7 @@ class Compiler : public ErrorSink { } } virtual void gUnaryCmp(int op, Type* pResultType) { virtual void gUnaryCmp(int op) { if (op != OP_LOGICAL_NOT) { error("Unknown unary cmp %d", op); } else { Loading @@ -2039,7 +2028,7 @@ class Compiler : public ErrorSink { 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); Loading @@ -2062,7 +2051,7 @@ class Compiler : public ErrorSink { break; } } setR0Type(pResultType); setR0Type(mkpInt); } virtual void genUnaryOp(int op) { Loading Loading @@ -2116,7 +2105,31 @@ class Compiler : public ErrorSink { 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); Loading @@ -2141,7 +2154,8 @@ class Compiler : public ErrorSink { } } virtual void loadR0FromR0(Type* pPointerType) { virtual void loadR0FromR0() { Type* pPointerType = getR0Type(); assert(pPointerType->tag == TY_POINTER); switch (pPointerType->pHead->tag) { case TY_INT: Loading Loading @@ -2204,7 +2218,7 @@ class Compiler : public ErrorSink { } } 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: Loading @@ -2213,22 +2227,10 @@ class Compiler : public ErrorSink { } 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)); } break; case TY_FLOAT: if (ea < -LOCAL || ea > LOCAL) { Loading @@ -2236,9 +2238,6 @@ class Compiler : public ErrorSink { } 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) { Loading @@ -2246,9 +2245,6 @@ class Compiler : public ErrorSink { } 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); Loading Loading @@ -2535,9 +2531,9 @@ class Compiler : public ErrorSink { } /* 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) { Loading @@ -2558,9 +2554,9 @@ class Compiler : public ErrorSink { 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) { Loading @@ -2569,9 +2565,9 @@ class Compiler : public ErrorSink { } 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) { Loading @@ -2584,14 +2580,19 @@ class Compiler : public ErrorSink { 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) { Loading @@ -2604,9 +2605,9 @@ class Compiler : public ErrorSink { 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){ Loading Loading @@ -3814,7 +3815,7 @@ class Compiler : public ErrorSink { 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) { Loading Loading @@ -3869,7 +3870,7 @@ class Compiler : public ErrorSink { 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); Loading @@ -3886,7 +3887,7 @@ class Compiler : public ErrorSink { /* -, +, !, ~ */ unary(false); if (t == '!') pGen->gUnaryCmp(a, mkpInt); pGen->gUnaryCmp(a); else if (t == '+') { // ignore unary plus. } else { Loading Loading @@ -3917,9 +3918,9 @@ class Compiler : public ErrorSink { 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 Loading Loading @@ -3965,8 +3966,14 @@ class Compiler : public ErrorSink { 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(); } } Loading Loading @@ -4037,6 +4044,28 @@ 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) { Loading @@ -4061,10 +4090,10 @@ class Compiler : public ErrorSink { 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); } Loading @@ -4073,10 +4102,10 @@ class Compiler : public ErrorSink { /* && 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); } } } Loading Loading
libacc/acc.cpp +153 −124 Original line number Diff line number Diff line Loading @@ -282,6 +282,11 @@ class Compiler : public ErrorSink { } } /* 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; } Loading Loading @@ -312,7 +317,7 @@ class Compiler : public ErrorSink { 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; Loading @@ -333,7 +338,7 @@ class Compiler : public ErrorSink { * 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. Loading @@ -344,7 +349,7 @@ class Compiler : public ErrorSink { /* 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. Loading @@ -355,16 +360,18 @@ class Compiler : public ErrorSink { */ 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 Loading @@ -384,11 +391,8 @@ class Compiler : public ErrorSink { * 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. Loading Loading @@ -636,9 +640,9 @@ class Compiler : public ErrorSink { } /* 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) { Loading Loading @@ -685,14 +689,13 @@ class Compiler : public ErrorSink { 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: Loading Loading @@ -723,7 +726,6 @@ class Compiler : public ErrorSink { error("Unknown comparison op %d", op); break; } popType(); } else if (tagR0 == TY_DOUBLE || tagTOS == TY_DOUBLE) { setupDoubleArgs(); switch(op) { Loading Loading @@ -775,7 +777,7 @@ class Compiler : public ErrorSink { break; } } setR0Type(pResultType); setR0Type(mkpInt); } virtual void genOp(int op) { Loading @@ -786,6 +788,7 @@ class Compiler : public ErrorSink { 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) { Loading @@ -796,14 +799,12 @@ class Compiler : public ErrorSink { 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); } Loading @@ -812,7 +813,6 @@ class Compiler : public ErrorSink { 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. Loading @@ -831,12 +831,9 @@ class Compiler : public ErrorSink { 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 Loading Loading @@ -875,7 +872,6 @@ class Compiler : public ErrorSink { error("Unimplemented op %d\n", op); break; } popType(); } } else { Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType; Loading Loading @@ -922,7 +918,7 @@ class Compiler : public ErrorSink { } } virtual void gUnaryCmp(int op, Type* pResultType) { virtual void gUnaryCmp(int op) { if (op != OP_LOGICAL_NOT) { error("Unknown unary cmp %d", op); } else { Loading @@ -946,7 +942,7 @@ class Compiler : public ErrorSink { break; } } setR0Type(pResultType); setR0Type(mkpInt); } virtual void genUnaryOp(int op) { Loading Loading @@ -1005,7 +1001,28 @@ class Compiler : public ErrorSink { 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(); Loading @@ -1027,7 +1044,8 @@ class Compiler : public ErrorSink { } } virtual void loadR0FromR0(Type* pPointerType) { virtual void loadR0FromR0() { Type* pPointerType = getR0Type(); assert(pPointerType->tag == TY_POINTER); switch (pPointerType->pHead->tag) { case TY_INT: Loading Loading @@ -1149,7 +1167,7 @@ class Compiler : public ErrorSink { } } 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: Loading @@ -1170,10 +1188,6 @@ class Compiler : public ErrorSink { 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: Loading @@ -1195,37 +1209,6 @@ class Compiler : public ErrorSink { 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) { Loading Loading @@ -1563,6 +1546,12 @@ class Compiler : public ErrorSink { 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 Loading Loading @@ -1837,9 +1826,9 @@ class Compiler : public ErrorSink { } /* 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) { Loading Loading @@ -1879,7 +1868,7 @@ class Compiler : public ErrorSink { 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; Loading @@ -1890,7 +1879,7 @@ class Compiler : public ErrorSink { 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); Loading Loading @@ -1945,7 +1934,7 @@ class Compiler : public ErrorSink { } o(0xc0b60f); // movzbl %al, %eax } setR0Type(pResultType); setR0Type(mkpInt); } virtual void genOp(int op) { Loading Loading @@ -1973,7 +1962,7 @@ class Compiler : public ErrorSink { int size = sizeOf(pR0Type->pHead); if (size != 1) { pushR0(); li(size, mkpInt); li(size); // TODO: Optimize for power-of-two. genOp(OP_DIV); } Loading Loading @@ -2028,7 +2017,7 @@ class Compiler : public ErrorSink { } } virtual void gUnaryCmp(int op, Type* pResultType) { virtual void gUnaryCmp(int op) { if (op != OP_LOGICAL_NOT) { error("Unknown unary cmp %d", op); } else { Loading @@ -2039,7 +2028,7 @@ class Compiler : public ErrorSink { 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); Loading @@ -2062,7 +2051,7 @@ class Compiler : public ErrorSink { break; } } setR0Type(pResultType); setR0Type(mkpInt); } virtual void genUnaryOp(int op) { Loading Loading @@ -2116,7 +2105,31 @@ class Compiler : public ErrorSink { 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); Loading @@ -2141,7 +2154,8 @@ class Compiler : public ErrorSink { } } virtual void loadR0FromR0(Type* pPointerType) { virtual void loadR0FromR0() { Type* pPointerType = getR0Type(); assert(pPointerType->tag == TY_POINTER); switch (pPointerType->pHead->tag) { case TY_INT: Loading Loading @@ -2204,7 +2218,7 @@ class Compiler : public ErrorSink { } } 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: Loading @@ -2213,22 +2227,10 @@ class Compiler : public ErrorSink { } 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)); } break; case TY_FLOAT: if (ea < -LOCAL || ea > LOCAL) { Loading @@ -2236,9 +2238,6 @@ class Compiler : public ErrorSink { } 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) { Loading @@ -2246,9 +2245,6 @@ class Compiler : public ErrorSink { } 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); Loading Loading @@ -2535,9 +2531,9 @@ class Compiler : public ErrorSink { } /* 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) { Loading @@ -2558,9 +2554,9 @@ class Compiler : public ErrorSink { 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) { Loading @@ -2569,9 +2565,9 @@ class Compiler : public ErrorSink { } 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) { Loading @@ -2584,14 +2580,19 @@ class Compiler : public ErrorSink { 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) { Loading @@ -2604,9 +2605,9 @@ class Compiler : public ErrorSink { 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){ Loading Loading @@ -3814,7 +3815,7 @@ class Compiler : public ErrorSink { 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) { Loading Loading @@ -3869,7 +3870,7 @@ class Compiler : public ErrorSink { 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); Loading @@ -3886,7 +3887,7 @@ class Compiler : public ErrorSink { /* -, +, !, ~ */ unary(false); if (t == '!') pGen->gUnaryCmp(a, mkpInt); pGen->gUnaryCmp(a); else if (t == '+') { // ignore unary plus. } else { Loading Loading @@ -3917,9 +3918,9 @@ class Compiler : public ErrorSink { 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 Loading Loading @@ -3965,8 +3966,14 @@ class Compiler : public ErrorSink { 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(); } } Loading Loading @@ -4037,6 +4044,28 @@ 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) { Loading @@ -4061,10 +4090,10 @@ class Compiler : public ErrorSink { 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); } Loading @@ -4073,10 +4102,10 @@ class Compiler : public ErrorSink { /* && 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); } } } Loading