diff --git a/src/cmd/smlrc/cgmips.c b/src/cmd/smlrc/cgmips.c index e22bdc3..73ea5d9 100644 --- a/src/cmd/smlrc/cgmips.c +++ b/src/cmd/smlrc/cgmips.c @@ -516,13 +516,16 @@ void GenJumpIfNotZero(int label) } fpos_t GenPrologPos; +int GenLeaf; STATIC void GenWriteFrameSize(void) { - unsigned size = -CurFxnMinLocalOfs; - int pfx = size ? ' ' : '#'; - printf2("\t%csubu\t$29, $29, %10u\n", pfx, size); // 10 chars are enough for 32-bit unsigned ints + unsigned size = 8/*RA + FP*/ - CurFxnMinLocalOfs; + printf2("\tsubu\t$29, $29, %10u\n", size); // 10 chars are enough for 32-bit unsigned ints + printf2("\tsw\t$30, %10u($29)\n", size - 8); + printf2("\taddu\t$30, $29, %10u\n", size - 8); + printf2("\t%csw\t$31, 4($30)\n", GenLeaf ? '#' : ' '); } STATIC @@ -538,23 +541,6 @@ void GenUpdateFrameSize(void) STATIC void GenFxnProlog(void) { - GenPrintInstr3Operands(MipsInstrSubU, 0, - MipsOpRegSp, 0, - MipsOpRegSp, 0, - MipsOpConst, 8); - - GenPrintInstr2Operands(MipsInstrSW, 0, - MipsOpRegRa, 0, - MipsOpIndRegSp, 4); - - GenPrintInstr2Operands(MipsInstrSW, 0, - MipsOpRegFp, 0, - MipsOpIndRegSp, 0); - - GenPrintInstr2Operands(MipsInstrMov, 0, - MipsOpRegFp, 0, - MipsOpRegSp, 0); - if (CurFxnParamCntMax) { int i, cnt = CurFxnParamCntMax; @@ -563,9 +549,11 @@ void GenFxnProlog(void) for (i = 0; i < cnt; i++) GenPrintInstr2Operands(MipsInstrSW, 0, MipsOpRegA0 + i, 0, - MipsOpIndRegFp, 8 + 4 * i); + MipsOpIndRegSp, 4 * i); } + GenLeaf = 1; // will be reset to 0 if a call is generated + fgetpos(OutFile, &GenPrologPos); GenWriteFrameSize(); } @@ -586,22 +574,19 @@ void GenFxnEpilog(void) { GenUpdateFrameSize(); - GenPrintInstr2Operands(MipsInstrMov, 0, - MipsOpRegSp, 0, - MipsOpRegFp, 0); + if (!GenLeaf) + GenPrintInstr2Operands(MipsInstrLW, 0, + MipsOpRegRa, 0, + MipsOpIndRegFp, 4); GenPrintInstr2Operands(MipsInstrLW, 0, MipsOpRegFp, 0, - MipsOpIndRegSp, 0); - - GenPrintInstr2Operands(MipsInstrLW, 0, - MipsOpRegRa, 0, - MipsOpIndRegSp, 4); + MipsOpIndRegFp, 0); GenPrintInstr3Operands(MipsInstrAddU, 0, MipsOpRegSp, 0, MipsOpRegSp, 0, - MipsOpConst, 8); + MipsOpConst, 8/*RA + FP*/ - CurFxnMinLocalOfs); GenPrintInstr1Operand(MipsInstrJ, 0, MipsOpRegRa, 0); @@ -1053,6 +1038,8 @@ void GenPopReg(void) #define tokRevIdent 0x100 #define tokRevLocalOfs 0x101 +#define tokAssign0 0x102 +#define tokNum0 0x103 STATIC void GenPrep(int* idx) @@ -1103,6 +1090,7 @@ void GenPrep(int* idx) stack[oldIdxRight + 1][0] = tokNumInt; // reduce the number of cases since tokNumInt and tokNumUint are handled the same way // fallthrough case tokNumInt: + case tokNum0: case tokIdent: case tokLocalOfs: break; @@ -1142,6 +1130,16 @@ void GenPrep(int* idx) break; case '=': + if (oldIdxRight + 1 == sp - 1 && + (stack[oldIdxRight][0] == tokNumInt || stack[oldIdxRight][0] == tokNumUint) && + truncUint(stack[oldIdxRight][1]) == 0) + { + // Special case for assigning 0 while throwing away the expression result value + // TBD??? , + stack[oldIdxRight][0] = tokNum0; // this zero constant will not be loaded into a register + stack[oldIdxRight + 1][0] = tokAssign0; // change '=' to tokAssign0 + } + // fallthrough case tokAssignAdd: case tokAssignSub: case tokAssignMul: @@ -1536,7 +1534,7 @@ void GenExpr0(void) int paramOfs = 0; int t = sp - 1; - if (stack[t][0] == tokIf || stack[t][0] == tokIfNot) + if (stack[t][0] == tokIf || stack[t][0] == tokIfNot || stack[t][0] == tokReturn) t--; GenPrep(&t); @@ -1575,7 +1573,7 @@ void GenExpr0(void) case tokGoto: printf2(" # sh-circ-goto "); break; case tokLogAnd: printf2(" # short-circuit && target\n"); break; case tokLogOr: printf2(" # short-circuit || target\n"); break; - case tokIf: case tokIfNot: break; + case tokIf: case tokIfNot: case tokReturn: break; default: printf2(" # %s\n", GetTokenName(tok)); break; } #endif @@ -1675,6 +1673,7 @@ void GenExpr0(void) break; case ')': + GenLeaf = 0; if (maxCallDepth != 1) { if (v >= 4) @@ -2021,6 +2020,21 @@ void GenExpr0(void) GenExtendRegIfNeeded(GenWreg, v); break; + case tokAssign0: // assignment of 0, while throwing away the expression result value + if (stack[i - 1][0] == tokRevLocalOfs) + { + GenWriteLocal(MipsOpRegZero, v, stack[i - 1][1]); + } + else if (stack[i - 1][0] == tokRevIdent) + { + GenWriteIdent(MipsOpRegZero, v, stack[i - 1][1]); + } + else + { + GenWriteIndirect(GenWreg, MipsOpRegZero, v); + } + break; + case '<': GenCmp(&i, 0x00); break; case tokLEQ: GenCmp(&i, 0x01); break; case '>': GenCmp(&i, 0x02); break; @@ -2116,6 +2130,8 @@ void GenExpr0(void) case tokRevIdent: case tokRevLocalOfs: case tokComma: + case tokReturn: + case tokNum0: break; case tokIf: diff --git a/src/cmd/smlrc/cgx86.c b/src/cmd/smlrc/cgx86.c index 7c519a5..0b70742 100644 --- a/src/cmd/smlrc/cgx86.c +++ b/src/cmd/smlrc/cgx86.c @@ -1783,7 +1783,7 @@ void GenExpr1(void) int s = sp - 1; int i; - if (stack[s][0] == tokIf || stack[s][0] == tokIfNot) + if (stack[s][0] == tokIf || stack[s][0] == tokIfNot || stack[s][0] == tokReturn) s--; GenFuse(&s); @@ -1860,6 +1860,8 @@ void GenExpr1(void) case tokIfNot: printf2("IF!"); break; + case tokReturn: + break; default: printf2("%s", GetTokenName(tok)); switch (tok) @@ -2667,6 +2669,7 @@ void GenExpr1(void) case '(': case tokIf: case tokIfNot: + case tokReturn: break; case tokVoid: @@ -2708,7 +2711,7 @@ void GenExpr0(void) case tokGoto: printf2("; sh-circ-goto "); break; case tokLogAnd: printf2("; short-circuit && target\n"); break; case tokLogOr: printf2("; short-circuit || target\n"); break; - case tokIf: case tokIfNot: break; + case tokIf: case tokIfNot: case tokReturn: break; default: printf2("; %s\n", GetTokenName(tok)); break; } #endif @@ -3104,6 +3107,7 @@ void GenExpr0(void) case tokComma: case ',': case '(': + case tokReturn: break; case tokIf: diff --git a/src/cmd/smlrc/smlrc.c b/src/cmd/smlrc/smlrc.c index 9c13bc7..d53af7e 100644 --- a/src/cmd/smlrc/smlrc.c +++ b/src/cmd/smlrc/smlrc.c @@ -188,7 +188,7 @@ int fsetpos(FILE*, fpos_t*); #endif #ifndef MAX_IDENT_TABLE_LEN -#define MAX_IDENT_TABLE_LEN (4096+656+32) // must be greater than MAX_IDENT_LEN +#define MAX_IDENT_TABLE_LEN (4096+656+64) // must be greater than MAX_IDENT_LEN #endif #ifndef SYNTAX_STACK_MAX @@ -338,7 +338,7 @@ int fsetpos(FILE*, fpos_t*); #define SymFuncPtr 3 #ifndef STACK_SIZE -#define STACK_SIZE 128 +#define STACK_SIZE 129 #endif #define SymFxn 1 @@ -651,6 +651,7 @@ char* CurFxnName = NULL; #ifndef NO_FUNC_ int CurFxnNameLabel = 0; #endif +int Main; // if inside main() int ParseLevel = 0; // Parse level/scope (file:0, fxn:1+) int ParamLevel = 0; // 1+ if parsing params, 0 otherwise @@ -6927,7 +6928,6 @@ int ParseDecl(int tok, unsigned structInfo[4], int cast, int label) int undoSymbolsPtr = SyntaxStackCnt; int undoIdents = IdentTableLen; int i; - int Main; #ifndef NO_ANNOTATIONS DumpDecl(lastSyntaxPtr, 0); @@ -6993,6 +6993,7 @@ int ParseDecl(int tok, unsigned structInfo[4], int cast, int label) { sp = 0; push(tokNumInt); + push(tokReturn); // value produced by generated code is used GenExpr(); } @@ -7452,15 +7453,20 @@ int ParseStatement(int tok, int BrkCntTarget[2], int casesIdx) } } } + push(tokReturn); // value produced by generated code is used GenExpr(); } - GenJumpUncond(CurFxnEpilogLabel); tok = GetToken(); + // If this return is the last statement in the function, the epilogue immediately + // follows and there's no need to jump to it. + if (!(tok == '}' && ParseLevel == 1 && !Main)) + GenJumpUncond(CurFxnEpilogLabel); } else if (tok == tokWhile) { int labelBefore = LabelCnt++; int labelAfter = LabelCnt++; + int forever = 0; #ifndef NO_ANNOTATIONS GenStartCommentLine(); printf2("while\n"); #endif @@ -7485,25 +7491,35 @@ int ParseStatement(int tok, int BrkCntTarget[2], int casesIdx) GenNumLabel(labelBefore); - switch (stack[sp - 1][0]) + if (constExpr) { - case '<': - case '>': - case tokEQ: - case tokNEQ: - case tokLEQ: - case tokGEQ: - case tokULess: - case tokUGreater: - case tokULEQ: - case tokUGEQ: - push2(tokIfNot, labelAfter); - GenExpr(); - break; - default: - GenExpr(); - GenJumpIfZero(labelAfter); - break; + // Special cases for while(0) and while(1) + if (!(forever = truncInt(exprVal))) + GenJumpUncond(labelAfter); + } + else + { + switch (stack[sp - 1][0]) + { + case '<': + case '>': + case tokEQ: + case tokNEQ: + case tokLEQ: + case tokGEQ: + case tokULess: + case tokUGreater: + case tokULEQ: + case tokUGEQ: + push2(tokIfNot, labelAfter); + GenExpr(); + break; + default: + push(tokReturn); // value produced by generated code is used + GenExpr(); + GenJumpIfZero(labelAfter); + break; + } } tok = GetToken(); @@ -7511,7 +7527,9 @@ int ParseStatement(int tok, int BrkCntTarget[2], int casesIdx) brkCntTarget[1] = labelBefore; // continue target tok = ParseStatement(tok, brkCntTarget, casesIdx); - GenJumpUncond(labelBefore); + // Special case for while(0) + if (!(constExpr && !forever)) + GenJumpUncond(labelBefore); GenNumLabel(labelAfter); } else if (tok == tokDo) @@ -7560,25 +7578,35 @@ int ParseStatement(int tok, int BrkCntTarget[2], int casesIdx) GenNumLabel(labelWhile); - switch (stack[sp - 1][0]) + if (constExpr) { - case '<': - case '>': - case tokEQ: - case tokNEQ: - case tokLEQ: - case tokGEQ: - case tokULess: - case tokUGreater: - case tokULEQ: - case tokUGEQ: - push2(tokIf, labelBefore); - GenExpr(); - break; - default: - GenExpr(); - GenJumpIfNotZero(labelBefore); - break; + // Special cases for while(0) and while(1) + if (truncInt(exprVal)) + GenJumpUncond(labelBefore); + } + else + { + switch (stack[sp - 1][0]) + { + case '<': + case '>': + case tokEQ: + case tokNEQ: + case tokLEQ: + case tokGEQ: + case tokULess: + case tokUGreater: + case tokULEQ: + case tokUGEQ: + push2(tokIf, labelBefore); + GenExpr(); + break; + default: + push(tokReturn); // value produced by generated code is used + GenExpr(); + GenJumpIfNotZero(labelBefore); + break; + } } GenNumLabel(labelAfter); @@ -7611,25 +7639,35 @@ int ParseStatement(int tok, int BrkCntTarget[2], int casesIdx) //error("ParseStatement(): unexpected 'void' expression in 'if ( expression )'\n"); scalarTypeCheck(synPtr); - switch (stack[sp - 1][0]) + if (constExpr) { - case '<': - case '>': - case tokEQ: - case tokNEQ: - case tokLEQ: - case tokGEQ: - case tokULess: - case tokUGreater: - case tokULEQ: - case tokUGEQ: - push2(tokIfNot, labelAfterIf); - GenExpr(); - break; - default: - GenExpr(); - GenJumpIfZero(labelAfterIf); - break; + // Special cases for if(0) and if(1) + if (!truncInt(exprVal)) + GenJumpUncond(labelAfterIf); + } + else + { + switch (stack[sp - 1][0]) + { + case '<': + case '>': + case tokEQ: + case tokNEQ: + case tokLEQ: + case tokGEQ: + case tokULess: + case tokUGreater: + case tokULEQ: + case tokUGEQ: + push2(tokIfNot, labelAfterIf); + GenExpr(); + break; + default: + push(tokReturn); // value produced by generated code is used + GenExpr(); + GenJumpIfZero(labelAfterIf); + break; + } } tok = GetToken(); @@ -7658,6 +7696,9 @@ int ParseStatement(int tok, int BrkCntTarget[2], int casesIdx) int labelExpr3 = LabelCnt++; int labelBody = LabelCnt++; int labelAfter = LabelCnt++; + int cond = -1; + static int expr3Stack[STACK_SIZE / 2][2]; + static int expr3Sp; #ifndef NO_FOR_DECL int decl = 0; int undoSymbolsPtr = 0, undoLocalOfs = 0, undoIdents = 0; @@ -7709,46 +7750,97 @@ int ParseStatement(int tok, int BrkCntTarget[2], int casesIdx) //error("ParseStatement(): unexpected 'void' expression in 'for ( ; expression ; )'\n"); scalarTypeCheck(synPtr); - switch (stack[sp - 1][0]) + if (constExpr) { - case '<': - case '>': - case tokEQ: - case tokNEQ: - case tokLEQ: - case tokGEQ: - case tokULess: - case tokUGreater: - case tokULEQ: - case tokUGEQ: - push2(tokIfNot, labelAfter); - GenExpr(); - break; - default: - GenExpr(); - GenJumpIfZero(labelAfter); - break; + // Special cases for for(...; 0; ...) and for(...; 1; ...) + cond = truncInt(exprVal) != 0; + } + else + { + switch (stack[sp - 1][0]) + { + case '<': + case '>': + case tokEQ: + case tokNEQ: + case tokLEQ: + case tokGEQ: + case tokULess: + case tokUGreater: + case tokULEQ: + case tokUGEQ: + push2(tokIfNot, labelAfter); + GenExpr(); + break; + default: + push(tokReturn); // value produced by generated code is used + GenExpr(); + GenJumpIfZero(labelAfter); + break; + } } } - GenJumpUncond(labelBody); + else + { + // Special case for for(...; ; ...) + cond = 1; + } + if (!cond) + // Special case for for(...; 0; ...) + GenJumpUncond(labelAfter); - GenNumLabel(labelExpr3); tok = GetToken(); if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ')') //error("ParseStatement(): ')' expected after 'for ( expression ; expression ; expression'\n"); errorUnexpectedToken(tok); - if (gotUnary) - { - GenExpr(); - } - GenJumpUncond(labelBefore); - GenNumLabel(labelBody); - tok = GetToken(); - brkCntTarget[0] = labelAfter; // break target - brkCntTarget[1] = labelExpr3; // continue target - tok = ParseStatement(tok, brkCntTarget, casesIdx); - GenJumpUncond(labelExpr3); + // Try to reorder expr3 with body to reduce the number of jumps, favor small expr3's + if (gotUnary && sp <= 16 && (unsigned)sp <= sizeof expr3Stack / sizeof expr3Stack[0] - expr3Sp) + { + int cnt = sp; + // Stash the stack containing expr3 + memcpy(expr3Stack + expr3Sp, stack, cnt * sizeof stack[0]); + expr3Sp += cnt; + + // Body + tok = GetToken(); + brkCntTarget[0] = labelAfter; // break target + brkCntTarget[1] = labelExpr3; // continue target + tok = ParseStatement(tok, brkCntTarget, casesIdx); + + // Unstash expr3 and generate code for it + expr3Sp -= cnt; + memcpy(stack, expr3Stack + expr3Sp, cnt * sizeof stack[0]); + sp = cnt; + GenNumLabel(labelExpr3); + GenExpr(); + + // Special case for for(...; 0; ...) + if (cond) + GenJumpUncond(labelBefore); + } + else + { + if (gotUnary) + { + GenJumpUncond(labelBody); + // expr3 + GenNumLabel(labelExpr3); + GenExpr(); + GenJumpUncond(labelBefore); + GenNumLabel(labelBody); + } + + // Body + tok = GetToken(); + brkCntTarget[0] = labelAfter; // break target + brkCntTarget[1] = gotUnary ? labelExpr3 : (cond ? labelBefore : labelAfter); // continue target + tok = ParseStatement(tok, brkCntTarget, casesIdx); + + // Special case for for(...; 0; ...) + if (brkCntTarget[1] != labelAfter) + GenJumpUncond(brkCntTarget[1]); + } GenNumLabel(labelAfter); @@ -7818,6 +7910,7 @@ int ParseStatement(int tok, int BrkCntTarget[2], int casesIdx) //error("ParseStatement(): unexpected 'void' expression in 'switch ( expression )'\n"); scalarTypeCheck(synPtr); + push(tokReturn); // value produced by generated code is used GenExpr(); tok = GetToken();