Copy elision on return statements

This commit is contained in:
drmortalwombat 2023-07-05 17:10:23 +02:00
parent 0b79d44345
commit 0b6a9c3584
8 changed files with 168 additions and 16 deletions

View File

@ -270,6 +270,9 @@ void Expression::Dump(int ident) const
case EX_CLEANUP: case EX_CLEANUP:
printf("CLEANUP"); printf("CLEANUP");
break; break;
case EX_RESULT:
printf("RESULT");
break;
} }
printf("\n"); printf("\n");
@ -810,6 +813,15 @@ Declaration* Declaration::BuildPointer(const Location& loc)
return pdec; 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) Declaration* Declaration::Last(void)
{ {
mPrev = nullptr; mPrev = nullptr;
@ -1069,6 +1081,57 @@ bool Declaration::IsSubType(const Declaration* dec) const
return false; 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 bool Declaration::IsConstSame(const Declaration* dec) const
{ {
if (this == dec) if (this == dec)

View File

@ -187,7 +187,8 @@ enum ExpressionType
EX_ASSUME, EX_ASSUME,
EX_BANKOF, EX_BANKOF,
EX_CONSTRUCT, EX_CONSTRUCT,
EX_CLEANUP EX_CLEANUP,
EX_RESULT
}; };
class Expression class Expression
@ -247,6 +248,7 @@ public:
bool IsConstSame(const Declaration* dec) const; bool IsConstSame(const Declaration* dec) const;
bool IsSameValue(const Declaration* dec) const; bool IsSameValue(const Declaration* dec) const;
bool IsSameParams(const Declaration* dec) const; bool IsSameParams(const Declaration* dec) const;
bool IsSameMutable(const Declaration* dec) const;
bool IsIntegerType(void) const; bool IsIntegerType(void) const;
bool IsNumericType(void) const; bool IsNumericType(void) const;
@ -263,6 +265,7 @@ public:
Declaration* Last(void); Declaration* Last(void);
Declaration* BuildPointer(const Location& loc); Declaration* BuildPointer(const Location& loc);
Declaration* BuildReference(const Location& loc);
int Stride(void) const; int Stride(void) const;
}; };

View File

@ -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 (pdec && !(ldec->mBase->mFlags & DTF_VARIADIC) && !(ldec->mFlags & (DTF_INTRINSIC | DTF_FUNC_ASSEMBLER)))
{ {
#if 0 #if 1
if (mCompilerOptions & COPT_OPTIMIZE_BASIC) if (mCompilerOptions & COPT_OPTIMIZE_BASIC)
{ {
if (!(pdec->mFlags & DTF_FPARAM_NOCONST)) if (!(pdec->mFlags & DTF_FPARAM_NOCONST))

View File

@ -6879,6 +6879,10 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
vr.LimitMax(ins->mSrc[0].mIntConst - 1); vr.LimitMax(ins->mSrc[0].mIntConst - 1);
else if (ins->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND) else if (ins->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND)
vr.LimitMax(ins->mSrc[0].mRange.mMaxValue - 1); 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; break;
#endif #endif
default: default:
@ -11883,6 +11887,10 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams)
{ {
ins->mInvariant = false; ins->mInvariant = false;
} }
else if (ins->mSrc[0].mMemory == IM_PARAM && hasCall && aliasedParams[ins->mSrc[0].mVarIndex])
{
ins->mInvariant = false;
}
else else
{ {
for (int bj = 0; bj < body.Size(); bj++) for (int bj = 0; bj < body.Size(); bj++)
@ -16098,7 +16106,7 @@ void InterCodeProcedure::Close(void)
{ {
GrowingTypeArray tstack(IT_NONE); GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "main"); CheckFunc = !strcmp(mIdent->mString, "print");
mEntryBlock = mBlocks[0]; mEntryBlock = mBlocks[0];

View File

@ -1313,7 +1313,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
case EX_CONSTRUCT: case EX_CONSTRUCT:
{ {
if (exp->mLeft->mLeft) 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) if (exp->mLeft->mRight)
{ {
@ -1327,6 +1327,60 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
} }
break; 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: case EX_CLEANUP:
{ {
vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); 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)); InterCodeProcedure* proc = new InterCodeProcedure(mod, dec->mLocation, dec->mQualIdent, mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_BYTE_CODE));
#if 0 #if 0
if (proc->mIdent && !strcmp(proc->mIdent->mString, "main")) if (proc->mIdent && !strcmp(proc->mIdent->mString, "A::func"))
exp->Dump(0); exp->Dump(0);
#endif #endif
#if 0 #if 0

View File

@ -18971,6 +18971,8 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
i++; i++;
if (i == mEntryBlocks.Size()) if (i == mEntryBlocks.Size())
{ {
mEntryRequiredRegs += CPU_REG_A;
mIns.Insert(0, eb->mIns[index]); mIns.Insert(0, eb->mIns[index]);
mIns[0].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y; mIns[0].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y;
for (int i = 0; i < mEntryBlocks.Size(); i++) for (int i = 0; i < mEntryBlocks.Size(); i++)
@ -18992,6 +18994,8 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
i++; i++;
if (i == mEntryBlocks.Size()) if (i == mEntryBlocks.Size())
{ {
mEntryRequiredRegs += CPU_REG_X;
mIns.Insert(0, eb->mIns[index]); mIns.Insert(0, eb->mIns[index]);
mIns[0].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y; mIns[0].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y;
for (int i = 0; i < mEntryBlocks.Size(); i++) for (int i = 0; i < mEntryBlocks.Size(); i++)
@ -19013,6 +19017,8 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
i++; i++;
if (i == mEntryBlocks.Size()) if (i == mEntryBlocks.Size())
{ {
mEntryRequiredRegs += CPU_REG_Y;
mIns.Insert(0, eb->mIns[index]); mIns.Insert(0, eb->mIns[index]);
mIns[0].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y; mIns[0].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y;
for (int i = 0; i < mEntryBlocks.Size(); i++) for (int i = 0; i < mEntryBlocks.Size(); i++)
@ -24803,6 +24809,8 @@ bool NativeCodeBasicBlock::MoveAbsoluteLoadStoreUp(int at)
return false; return false;
if (mIns[at + 1].mMode == ASMIM_ABSOLUTE_Y && mIns[j].ChangesYReg()) if (mIns[at + 1].mMode == ASMIM_ABSOLUTE_Y && mIns[j].ChangesYReg())
return false; 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) if (mIns[j].mType == ASMIT_JSR)
return false; return false;
@ -33307,7 +33315,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
for (int i = 2; i + 1 < mIns.Size(); i++) 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 && 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)) if (MoveAbsoluteLoadStoreUp(i))
changed = true; changed = true;
@ -36550,7 +36558,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
else if ( else if (
mIns[i + 0].mType == ASMIT_LDA && 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 + 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[i + 3].mType == ASMIT_ADC)
{ {
mIns.Insert(i + 4, mIns[i + 0]); mIns.Insert(i + 4, mIns[i + 0]);

View File

@ -3172,9 +3172,12 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
{ {
pdec = mCompilationUnits->mScope->Insert(ndec->mQualIdent, ndec); pdec = mCompilationUnits->mScope->Insert(ndec->mQualIdent, ndec);
Declaration * ldec = mScope->Insert(ndec->mIdent, pdec ? pdec : ndec); if (ndec->mIdent == ndec->mQualIdent)
if (ldec && ldec != pdec) {
mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate definition"); Declaration* ldec = mScope->Insert(ndec->mIdent, pdec ? pdec : ndec);
if (ldec && ldec != pdec)
mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate definition");
}
} }
else else
pdec = mScope->Insert(ndec->mIdent, ndec); pdec = mScope->Insert(ndec->mIdent, ndec);
@ -4184,7 +4187,7 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp)
else else
return NOOVERLOAD; 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; dist += 1;
else if (ptype->IsSubType(etype)) else if (ptype->IsSubType(etype))
dist += 256; dist += 256;
@ -4819,7 +4822,9 @@ Expression* Parser::ParseMulExpression(bool lhs)
else else
nexp->mDecType = exp->mDecType; nexp->mDecType = exp->mDecType;
exp = nexp->ConstantFold(mErrors); exp = CheckOperatorOverload(nexp);
exp = exp->ConstantFold(mErrors);
} }
return exp; return exp;
@ -5322,6 +5327,7 @@ Expression* Parser::ParseFunction(Declaration * dec)
if (dec->mFlags & DTF_FUNC_THIS) if (dec->mFlags & DTF_FUNC_THIS)
mThisPointer = dec->mParams; mThisPointer = dec->mParams;
mReturnType = dec->mBase;
DeclarationScope* scope = new DeclarationScope(mScope, SLEVEL_FUNCTION); DeclarationScope* scope = new DeclarationScope(mScope, SLEVEL_FUNCTION);
mScope = scope; mScope = scope;
@ -5713,7 +5719,17 @@ Expression* Parser::ParseStatement(void)
mScanner->NextToken(); mScanner->NextToken();
exp = new Expression(mScanner->mLocation, EX_RETURN); exp = new Expression(mScanner->mLocation, EX_RETURN);
if (mScanner->mToken != TK_SEMICOLON) if (mScanner->mToken != TK_SEMICOLON)
{
exp->mLeft = CleanupExpression(ParseRExpression()); 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); ConsumeToken(TK_SEMICOLON);
break; break;
case TK_BREAK: case TK_BREAK:

View File

@ -13,7 +13,7 @@ public:
DeclarationScope * mGlobals, * mScope; DeclarationScope * mGlobals, * mScope;
int mLocalIndex; int mLocalIndex;
CompilationUnits * mCompilationUnits; CompilationUnits * mCompilationUnits;
Declaration * mThisPointer; Declaration * mThisPointer, * mReturnType;
LinkerSection * mCodeSection, * mDataSection, * mBSSection; LinkerSection * mCodeSection, * mDataSection, * mBSSection;