From 0b6a9c35843c257ed360dbe2e16178a888bb8722 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 5 Jul 2023 17:10:23 +0200 Subject: [PATCH] Copy elision on return statements --- oscar64/Declaration.cpp | 63 +++++++++++++++++++++++++++++++++ oscar64/Declaration.h | 5 ++- oscar64/GlobalAnalyzer.cpp | 2 +- oscar64/InterCode.cpp | 10 +++++- oscar64/InterCodeGenerator.cpp | 58 ++++++++++++++++++++++++++++-- oscar64/NativeCodeGenerator.cpp | 18 +++++++--- oscar64/Parser.cpp | 26 +++++++++++--- oscar64/Parser.h | 2 +- 8 files changed, 168 insertions(+), 16 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 99b56f6..520abe9 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -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) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index fab88ce..8f44b7d 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -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; }; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 20f2221..8d0bf1a 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -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)) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 6bb85ca..e28d5c0 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -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]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 81e9299..b909701 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -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 diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index de13f29..de92f06 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -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; @@ -36469,7 +36477,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass else if ( mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && mIns[i + 1].mType == ASMIT_ROL && mIns[i + 1].mMode == ASMIM_IMPLIED && - mIns[i + 2].mType == ASMIT_CLC && + mIns[i + 2].mType == ASMIT_CLC && mIns[i + 3].mType == ASMIT_ADC) { mIns[i + 1].mType = ASMIT_NOP; @@ -36536,7 +36544,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass progress = true; } else if ( - mIns[i + 0].mType == ASMIT_LDA && + mIns[i + 0].mType == ASMIT_LDA && mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !mIns[i + 0].MayBeChangedOnAddress(mIns[i + 1]) && mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mType == ASMIT_ORA && mIns[i + 3].SameEffectiveAddress(mIns[i + 0]) && mIns[i + 3].mMode != ASMIM_IMMEDIATE) @@ -36548,9 +36556,9 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass progress = true; } 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 + 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]); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 0e1caf2..c99c46e 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -3172,9 +3172,12 @@ 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 (ldec && ldec != pdec) - mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate definition"); + 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: diff --git a/oscar64/Parser.h b/oscar64/Parser.h index b0515fe..8691e9e 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -13,7 +13,7 @@ public: DeclarationScope * mGlobals, * mScope; int mLocalIndex; CompilationUnits * mCompilationUnits; - Declaration * mThisPointer; + Declaration * mThisPointer, * mReturnType; LinkerSection * mCodeSection, * mDataSection, * mBSSection;