Copy elision on return statements
This commit is contained in:
parent
0b79d44345
commit
0b6a9c3584
|
@ -270,6 +270,9 @@ void Expression::Dump(int ident) const
|
|||
case EX_CLEANUP:
|
||||
printf("CLEANUP");
|
||||
break;
|
||||
case EX_RESULT:
|
||||
printf("RESULT");
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
|
@ -810,6 +813,15 @@ Declaration* Declaration::BuildPointer(const Location& loc)
|
|||
return pdec;
|
||||
}
|
||||
|
||||
Declaration* Declaration::BuildReference(const Location& loc)
|
||||
{
|
||||
Declaration* pdec = new Declaration(loc, DT_TYPE_REFERENCE);
|
||||
pdec->mBase = this;
|
||||
pdec->mFlags = DTF_DEFINED;
|
||||
pdec->mSize = 2;
|
||||
return pdec;
|
||||
}
|
||||
|
||||
Declaration* Declaration::Last(void)
|
||||
{
|
||||
mPrev = nullptr;
|
||||
|
@ -1069,6 +1081,57 @@ bool Declaration::IsSubType(const Declaration* dec) const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Declaration::IsSameMutable(const Declaration* dec) const
|
||||
{
|
||||
if (this == dec)
|
||||
return true;
|
||||
if (mType != dec->mType)
|
||||
return false;
|
||||
if (mSize != dec->mSize)
|
||||
return false;
|
||||
if (mStripe != dec->mStripe)
|
||||
return false;
|
||||
|
||||
if ((mFlags & DTF_SIGNED) != (dec->mFlags & DTF_SIGNED))
|
||||
return false;
|
||||
if ((dec->mFlags & DTF_CONST) && !(mFlags & DTF_CONST))
|
||||
return false;
|
||||
|
||||
if (mType == DT_TYPE_INTEGER)
|
||||
return true;
|
||||
else if (mType == DT_TYPE_BOOL || mType == DT_TYPE_FLOAT || mType == DT_TYPE_VOID)
|
||||
return true;
|
||||
else if (mType == DT_TYPE_ENUM)
|
||||
return mIdent == dec->mIdent;
|
||||
else if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY)
|
||||
return this->Stride() == dec->Stride() && mBase->IsSame(dec->mBase);
|
||||
else if (mType == DT_TYPE_STRUCT)
|
||||
return mScope == dec->mScope || (mIdent == dec->mIdent && mSize == dec->mSize);
|
||||
else if (mType == DT_TYPE_FUNCTION)
|
||||
{
|
||||
if (!mBase->IsSame(dec->mBase))
|
||||
return false;
|
||||
Declaration* dl = mParams, * dr = dec->mParams;
|
||||
while (dl && dr)
|
||||
{
|
||||
if (!dl->mBase->IsSame(dr->mBase))
|
||||
return false;
|
||||
dl = dl->mNext;
|
||||
dr = dr->mNext;
|
||||
}
|
||||
|
||||
if (dl || dr)
|
||||
return false;
|
||||
|
||||
if ((mFlags & DTF_VARIADIC) != (dec->mFlags & DTF_VARIADIC))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Declaration::IsConstSame(const Declaration* dec) const
|
||||
{
|
||||
if (this == dec)
|
||||
|
|
|
@ -187,7 +187,8 @@ enum ExpressionType
|
|||
EX_ASSUME,
|
||||
EX_BANKOF,
|
||||
EX_CONSTRUCT,
|
||||
EX_CLEANUP
|
||||
EX_CLEANUP,
|
||||
EX_RESULT
|
||||
};
|
||||
|
||||
class Expression
|
||||
|
@ -247,6 +248,7 @@ public:
|
|||
bool IsConstSame(const Declaration* dec) const;
|
||||
bool IsSameValue(const Declaration* dec) const;
|
||||
bool IsSameParams(const Declaration* dec) const;
|
||||
bool IsSameMutable(const Declaration* dec) const;
|
||||
|
||||
bool IsIntegerType(void) const;
|
||||
bool IsNumericType(void) const;
|
||||
|
@ -263,6 +265,7 @@ public:
|
|||
Declaration* Last(void);
|
||||
|
||||
Declaration* BuildPointer(const Location& loc);
|
||||
Declaration* BuildReference(const Location& loc);
|
||||
|
||||
int Stride(void) const;
|
||||
};
|
||||
|
|
|
@ -687,7 +687,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
|
||||
if (pdec && !(ldec->mBase->mFlags & DTF_VARIADIC) && !(ldec->mFlags & (DTF_INTRINSIC | DTF_FUNC_ASSEMBLER)))
|
||||
{
|
||||
#if 0
|
||||
#if 1
|
||||
if (mCompilerOptions & COPT_OPTIMIZE_BASIC)
|
||||
{
|
||||
if (!(pdec->mFlags & DTF_FPARAM_NOCONST))
|
||||
|
|
|
@ -6879,6 +6879,10 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
|
|||
vr.LimitMax(ins->mSrc[0].mIntConst - 1);
|
||||
else if (ins->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND)
|
||||
vr.LimitMax(ins->mSrc[0].mRange.mMaxValue - 1);
|
||||
else if (ins->mSrc[1].mRange.mMaxState == IntegerValueRange::S_BOUND)
|
||||
vr.LimitMax(ins->mSrc[1].mRange.mMaxValue);
|
||||
else
|
||||
vr.mMaxState = IntegerValueRange::S_UNBOUND;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
@ -11883,6 +11887,10 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams)
|
|||
{
|
||||
ins->mInvariant = false;
|
||||
}
|
||||
else if (ins->mSrc[0].mMemory == IM_PARAM && hasCall && aliasedParams[ins->mSrc[0].mVarIndex])
|
||||
{
|
||||
ins->mInvariant = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int bj = 0; bj < body.Size(); bj++)
|
||||
|
@ -16098,7 +16106,7 @@ void InterCodeProcedure::Close(void)
|
|||
{
|
||||
GrowingTypeArray tstack(IT_NONE);
|
||||
|
||||
CheckFunc = !strcmp(mIdent->mString, "main");
|
||||
CheckFunc = !strcmp(mIdent->mString, "print");
|
||||
|
||||
mEntryBlock = mBlocks[0];
|
||||
|
||||
|
|
|
@ -1313,7 +1313,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
|||
case EX_CONSTRUCT:
|
||||
{
|
||||
if (exp->mLeft->mLeft)
|
||||
TranslateExpression(procType, proc, block, exp->mLeft->mLeft, destack, breakBlock, continueBlock, inlineMapper);
|
||||
TranslateExpression(procType, proc, block, exp->mLeft->mLeft, destack, breakBlock, continueBlock, inlineMapper, lrexp);
|
||||
|
||||
if (exp->mLeft->mRight)
|
||||
{
|
||||
|
@ -1327,6 +1327,60 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
|||
}
|
||||
break;
|
||||
|
||||
case EX_RESULT:
|
||||
{
|
||||
if (lrexp)
|
||||
return *lrexp;
|
||||
|
||||
InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT);
|
||||
|
||||
if (inlineMapper)
|
||||
{
|
||||
if (inlineMapper->mResultExp)
|
||||
{
|
||||
ains->mDst.mTemp = inlineMapper->mResultExp->mTemp;
|
||||
}
|
||||
else
|
||||
{
|
||||
ains->mCode = IC_CONSTANT;
|
||||
ains->mDst.mType = IT_POINTER;
|
||||
ains->mDst.mTemp = proc->AddTemporary(IT_POINTER);
|
||||
ains->mConst.mOperandSize = procType->mBase->mSize;
|
||||
ains->mConst.mIntConst = 0;
|
||||
ains->mConst.mVarIndex = inlineMapper->mResult;
|
||||
ains->mConst.mMemory = IM_LOCAL;
|
||||
block->Append(ains);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InterInstruction* pins = new InterInstruction(exp->mLocation, IC_CONSTANT);
|
||||
pins->mDst.mType = IT_POINTER;
|
||||
pins->mDst.mTemp = proc->AddTemporary(IT_POINTER);
|
||||
pins->mConst.mVarIndex = 0;
|
||||
pins->mConst.mIntConst = 0;
|
||||
pins->mConst.mOperandSize = 2;
|
||||
if (procType->mFlags & DTF_FASTCALL)
|
||||
{
|
||||
pins->mConst.mMemory = IM_FPARAM;
|
||||
pins->mConst.mVarIndex += procType->mFastCallBase;
|
||||
}
|
||||
else
|
||||
pins->mConst.mMemory = IM_PARAM;
|
||||
block->Append(pins);
|
||||
|
||||
ains->mCode = IC_LOAD;
|
||||
ains->mSrc[0].mMemory = IM_INDIRECT;
|
||||
ains->mSrc[0].mType = IT_POINTER;
|
||||
ains->mSrc[0].mTemp = pins->mDst.mTemp;
|
||||
ains->mDst.mType = IT_POINTER;
|
||||
ains->mDst.mTemp = proc->AddTemporary(IT_POINTER);
|
||||
ains->mNumOperands = 1;
|
||||
block->Append(ains);
|
||||
}
|
||||
|
||||
return ExValue(exp->mDecType, ains->mDst.mTemp, 1);
|
||||
}
|
||||
case EX_CLEANUP:
|
||||
{
|
||||
vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
|
||||
|
@ -4453,7 +4507,7 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod
|
|||
InterCodeProcedure* proc = new InterCodeProcedure(mod, dec->mLocation, dec->mQualIdent, mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_BYTE_CODE));
|
||||
|
||||
#if 0
|
||||
if (proc->mIdent && !strcmp(proc->mIdent->mString, "main"))
|
||||
if (proc->mIdent && !strcmp(proc->mIdent->mString, "A::func"))
|
||||
exp->Dump(0);
|
||||
#endif
|
||||
#if 0
|
||||
|
|
|
@ -18971,6 +18971,8 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
|
|||
i++;
|
||||
if (i == mEntryBlocks.Size())
|
||||
{
|
||||
mEntryRequiredRegs += CPU_REG_A;
|
||||
|
||||
mIns.Insert(0, eb->mIns[index]);
|
||||
mIns[0].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y;
|
||||
for (int i = 0; i < mEntryBlocks.Size(); i++)
|
||||
|
@ -18992,6 +18994,8 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
|
|||
i++;
|
||||
if (i == mEntryBlocks.Size())
|
||||
{
|
||||
mEntryRequiredRegs += CPU_REG_X;
|
||||
|
||||
mIns.Insert(0, eb->mIns[index]);
|
||||
mIns[0].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y;
|
||||
for (int i = 0; i < mEntryBlocks.Size(); i++)
|
||||
|
@ -19013,6 +19017,8 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
|
|||
i++;
|
||||
if (i == mEntryBlocks.Size())
|
||||
{
|
||||
mEntryRequiredRegs += CPU_REG_Y;
|
||||
|
||||
mIns.Insert(0, eb->mIns[index]);
|
||||
mIns[0].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y;
|
||||
for (int i = 0; i < mEntryBlocks.Size(); i++)
|
||||
|
@ -24803,6 +24809,8 @@ bool NativeCodeBasicBlock::MoveAbsoluteLoadStoreUp(int at)
|
|||
return false;
|
||||
if (mIns[at + 1].mMode == ASMIM_ABSOLUTE_Y && mIns[j].ChangesYReg())
|
||||
return false;
|
||||
if (mIns[at + 1].mMode == ASMIM_INDIRECT_Y && (mIns[j].ChangesYReg() || mIns[j].ChangesZeroPage(mIns[at + 1].mAddress) || mIns[j].ChangesZeroPage(mIns[at + 1].mAddress + 1)))
|
||||
return false;
|
||||
|
||||
if (mIns[j].mType == ASMIT_JSR)
|
||||
return false;
|
||||
|
@ -33307,7 +33315,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
|||
for (int i = 2; i + 1 < mIns.Size(); i++)
|
||||
{
|
||||
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_STA &&
|
||||
(mIns[i + 1].mMode == ASMIM_ABSOLUTE || mIns[i + 1].mMode == ASMIM_ABSOLUTE_X || mIns[i + 1].mMode == ASMIM_ABSOLUTE_Y))
|
||||
(mIns[i + 1].mMode == ASMIM_ABSOLUTE || mIns[i + 1].mMode == ASMIM_ABSOLUTE_X || mIns[i + 1].mMode == ASMIM_ABSOLUTE_Y || mIns[i + 1].mMode == ASMIM_INDIRECT_Y))
|
||||
{
|
||||
if (MoveAbsoluteLoadStoreUp(i))
|
||||
changed = true;
|
||||
|
@ -36550,7 +36558,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
|||
else if (
|
||||
mIns[i + 0].mType == ASMIT_LDA &&
|
||||
mIns[i + 1].mType == ASMIT_EOR && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0xff &&
|
||||
mIns[i + 2].mType == ASMIT_SEC &&
|
||||
(mIns[i + 2].mType == ASMIT_SEC || mIns[i + 2].mType == ASMIT_CLC) &&
|
||||
mIns[i + 3].mType == ASMIT_ADC)
|
||||
{
|
||||
mIns.Insert(i + 4, mIns[i + 0]);
|
||||
|
|
|
@ -3172,10 +3172,13 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
|
|||
{
|
||||
pdec = mCompilationUnits->mScope->Insert(ndec->mQualIdent, ndec);
|
||||
|
||||
Declaration * ldec = mScope->Insert(ndec->mIdent, pdec ? pdec : ndec);
|
||||
if (ndec->mIdent == ndec->mQualIdent)
|
||||
{
|
||||
Declaration* ldec = mScope->Insert(ndec->mIdent, pdec ? pdec : ndec);
|
||||
if (ldec && ldec != pdec)
|
||||
mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate definition");
|
||||
}
|
||||
}
|
||||
else
|
||||
pdec = mScope->Insert(ndec->mIdent, ndec);
|
||||
|
||||
|
@ -4184,7 +4187,7 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp)
|
|||
else
|
||||
return NOOVERLOAD;
|
||||
}
|
||||
else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_ARRAY && ptype->mBase->IsSame(etype->mBase))
|
||||
else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_ARRAY && ptype->mBase->IsSameMutable(etype->mBase))
|
||||
dist += 1;
|
||||
else if (ptype->IsSubType(etype))
|
||||
dist += 256;
|
||||
|
@ -4819,7 +4822,9 @@ Expression* Parser::ParseMulExpression(bool lhs)
|
|||
else
|
||||
nexp->mDecType = exp->mDecType;
|
||||
|
||||
exp = nexp->ConstantFold(mErrors);
|
||||
exp = CheckOperatorOverload(nexp);
|
||||
|
||||
exp = exp->ConstantFold(mErrors);
|
||||
}
|
||||
|
||||
return exp;
|
||||
|
@ -5322,6 +5327,7 @@ Expression* Parser::ParseFunction(Declaration * dec)
|
|||
if (dec->mFlags & DTF_FUNC_THIS)
|
||||
mThisPointer = dec->mParams;
|
||||
|
||||
mReturnType = dec->mBase;
|
||||
|
||||
DeclarationScope* scope = new DeclarationScope(mScope, SLEVEL_FUNCTION);
|
||||
mScope = scope;
|
||||
|
@ -5713,7 +5719,17 @@ Expression* Parser::ParseStatement(void)
|
|||
mScanner->NextToken();
|
||||
exp = new Expression(mScanner->mLocation, EX_RETURN);
|
||||
if (mScanner->mToken != TK_SEMICOLON)
|
||||
{
|
||||
exp->mLeft = CleanupExpression(ParseRExpression());
|
||||
if (exp->mLeft->mType == EX_CONSTRUCT && mReturnType && mReturnType->mType == DT_TYPE_STRUCT)
|
||||
{
|
||||
Expression* cexp = exp->mLeft->mLeft->mLeft;
|
||||
|
||||
exp->mLeft->mLeft->mRight = nullptr;
|
||||
|
||||
exp->mLeft->mRight->mType = EX_RESULT;
|
||||
}
|
||||
}
|
||||
ConsumeToken(TK_SEMICOLON);
|
||||
break;
|
||||
case TK_BREAK:
|
||||
|
|
|
@ -13,7 +13,7 @@ public:
|
|||
DeclarationScope * mGlobals, * mScope;
|
||||
int mLocalIndex;
|
||||
CompilationUnits * mCompilationUnits;
|
||||
Declaration * mThisPointer;
|
||||
Declaration * mThisPointer, * mReturnType;
|
||||
|
||||
LinkerSection * mCodeSection, * mDataSection, * mBSSection;
|
||||
|
||||
|
|
Loading…
Reference in New Issue