Merge pull request #62 from alexfru/master

Smaller C: improvements.
This commit is contained in:
Serge Vakulenko
2015-08-29 10:35:45 -07:00
3 changed files with 237 additions and 124 deletions

View File

@@ -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:

View File

@@ -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:

View File

@@ -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();