From 6b753c14184ce95d09fed824e86c524d1da2ee7c Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 25 Jun 2023 14:25:29 +0200 Subject: [PATCH] Destructor tracking of temporary variables --- autotest/autotest.bat | 6 + autotest/constructortest.cpp | 165 ++++++ autotest/copyconstructor.cpp | 216 +++++++ oscar64/Declaration.cpp | 162 +++++- oscar64/Declaration.h | 8 +- oscar64/Errors.h | 4 +- oscar64/GlobalAnalyzer.cpp | 29 +- oscar64/InterCode.cpp | 2 +- oscar64/InterCodeGenerator.cpp | 514 ++++++++++++++--- oscar64/InterCodeGenerator.h | 8 +- oscar64/NativeCodeGenerator.cpp | 40 +- oscar64/Parser.cpp | 989 ++++++++++++++++++++++++++------ oscar64/Parser.h | 9 + oscar64/Scanner.cpp | 11 + 14 files changed, 1898 insertions(+), 265 deletions(-) create mode 100644 autotest/constructortest.cpp create mode 100644 autotest/copyconstructor.cpp diff --git a/autotest/autotest.bat b/autotest/autotest.bat index adc8e42..2b2ddd1 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -1,5 +1,11 @@ rem @echo off +@call :test constructortest.cpp +@if %errorlevel% neq 0 goto :error + +@call :test copyconstructor.cpp +@if %errorlevel% neq 0 goto :error + @call :test stdlibtest.c @if %errorlevel% neq 0 goto :error diff --git a/autotest/constructortest.cpp b/autotest/constructortest.cpp new file mode 100644 index 0000000..1418277 --- /dev/null +++ b/autotest/constructortest.cpp @@ -0,0 +1,165 @@ +#include + +int t, n; + +struct C1 +{ + int a; + + C1(int x); + ~C1(void); +}; + +C1::C1(int x) : a(x) +{ + t += a; + n++; +} + +C1::~C1(void) +{ + t -= a; +} + +void test_base(void) +{ + n = 0; + + { + C1 x(2); + C1 y(1); + } + + assert(t == 0 && n == 2); +} + +void test_base_loop(void) +{ + n = 0; + + for(int i=0; i<10; i++) + { + C1 x(2); + C1 y(1); + } + + assert(t == 0 && n == 20); +} + +struct C2 +{ + C1 c, d; + + C2(void); +}; + +C2::C2(void) + : c(7), d(11) +{ + +} + +void test_member(void) +{ + n = 0; + + { + C2 x(); + C2 y(); + } + + assert(t == 0 && n == 4); +} + +void test_member_loop(void) +{ + n = 0; + + for(int i=0; i<10; i++) + { + C2 x(); + C2 y(); + } + + assert(t == 0 && n == 40); +} + +struct C3 +{ + C2 x, y; +}; + +void test_default(void) +{ + n = 0; + + { + C3 x(); + C3 y(); + } + + assert(t == 0 && n == 8); +} + +void test_default_loop(void) +{ + n = 0; + + for(int i=0; i<10; i++) + { + C3 x(); + C3 y(); + } + + assert(t == 0 && n == 80); +} + +inline void test_inline_x(void) +{ + C1 x(1), y(2); +} + +void test_inline(void) +{ + n = 0; + + test_inline_x(); + + assert(t == 0 && n == 2); +} + +inline void test_inline_xr(void) +{ + C1 x(1), y(2); + + { + C1 x(3); + return; + } +} + +void test_inline_return(void) +{ + n = 0; + + test_inline_xr(); + + assert(t == 0 && n == 3); +} + +int main(void) +{ + test_base(); + test_base_loop(); + + test_member(); + test_member_loop(); + + test_default(); + test_default_loop(); + + test_inline(); + test_inline_return(); + + return 0; +} diff --git a/autotest/copyconstructor.cpp b/autotest/copyconstructor.cpp new file mode 100644 index 0000000..c16f30b --- /dev/null +++ b/autotest/copyconstructor.cpp @@ -0,0 +1,216 @@ +#include + +int t, n; + +struct C0 +{ + int u; + + C0(int a); + ~C0(void); +}; + +C0::C0(int a) : u(a) +{ + t += u; + n++; +} + +C0::~C0(void) +{ + t -= u; +} + +struct C1 +{ + int u; + + C1(int a); + ~C1(void); + C1(const C1 & c); +}; + +C1::C1(int a) : u(a) +{ + t += u; + n++; +} + +C1::~C1(void) +{ + t -= u; +} + +C1::C1(const C1 & c) : u(c.u) +{ + t += u; + n++; +} + +void test_dcopy_init(void) +{ + n = 0; + + { + C0 x(4); + C0 y(x); + } + + assert(n == 1 && t == -4); + + t = 0; +} + +void test_copy_init(void) +{ + n = 0; + + { + C1 x(4); + C1 y(x); + } + + assert(n == 2 && t == 0); +} + +struct C2 +{ + C1 a, b; + + C2(void); +}; + +C2::C2(void) : a(1), b(3) +{} + +void test_minit(void) +{ + n = 0; + + { + C2 x; + } + + assert(n == 2 && t == 0); +} + +void test_minit_copy(void) +{ + n = 0; + + { + C2 x; + C2 y(x); + } + + assert(n == 4 && t == 0); +} + +int k; + +inline void test_param_fv(C2 c) +{ + k += c.a.u; +} + +void test_param_fr(C2 & c) +{ + k += c.a.u; +} + +void test_param_value(void) +{ + n = 0; + + { + C2 x; + test_param_fv(x); + } + + assert(n == 4 && t == 0); +} + +void test_param_ref(void) +{ + n = 0; + + { + C2 x; + test_param_fr(x); + } + + assert(n == 2 && t == 0); +} + +C2 test_ret_v(void) +{ + C2 c; + return c; +} + +C2 & test_ret_r(C2 & r) +{ + return r; +} + +void test_return_value(void) +{ + n = 0; + + { + C2 c(test_ret_v()); + } + + assert(n == 4 && t == 0); +} + +void test_return_reference(void) +{ + n = 0; + + { + C2 d; + C2 c(test_ret_r(d)); + } + + assert(n == 2 && t == 0); +} + +void test_retparam_value(void) +{ + n = 0; + + { + test_param_fv(test_ret_v()); + } + + assert(n == 4 && t == 0); +} + +void test_retparam_reference(void) +{ + n = 0; + + { + test_param_fr(test_ret_v()); + } + + assert(n == 4 && t == 0); +} + +int main(void) +{ +#if 0 + test_dcopy_init(); + test_copy_init(); + test_minit(); + test_minit_copy(); + test_param_value(); + test_param_ref(); + test_return_value(); +#endif + test_retparam_value(); +// test_retparam_reference(); + + return 0; +} \ No newline at end of file diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 3f0af85..aa04d09 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -123,7 +123,7 @@ void DeclarationScope::End(const Location& loc) } Expression::Expression(const Location& loc, ExpressionType type) - : mLocation(loc), mEndLocation(loc), mType(type), mLeft(nullptr), mRight(nullptr), mConst(false) + : mLocation(loc), mEndLocation(loc), mType(type), mLeft(nullptr), mRight(nullptr), mConst(false), mDecType(nullptr), mDecValue(nullptr) { } @@ -133,6 +133,148 @@ Expression::~Expression(void) } +void Expression::Dump(int ident) const +{ + for (int i = 0; i < ident; i++) + printf("| "); + + switch (mType) + { + case EX_ERROR: + printf("ERROR"); + break; + case EX_VOID: + printf("VOID"); + break; + case EX_CONSTANT: + printf("CONST"); + break; + case EX_VARIABLE: + printf("VAR"); + break; + case EX_ASSIGNMENT: + printf("ASSIGN<%s>", TokenNames[mToken]); + break; + case EX_INITIALIZATION: + printf("INIT"); + break; + case EX_BINARY: + printf("BINARY<%s>", TokenNames[mToken]); + break; + case EX_RELATIONAL: + printf("RELATIONAL<%s>", TokenNames[mToken]); + break; + case EX_PREINCDEC: + printf("PREOP<%s>", TokenNames[mToken]); + break; + case EX_PREFIX: + printf("PREFIX<%s>", TokenNames[mToken]); + break; + case EX_POSTFIX: + printf("POSTFIX<%s>", TokenNames[mToken]); + break; + case EX_POSTINCDEC: + printf("POSTOP<%s>", TokenNames[mToken]); + break; + case EX_INDEX: + printf("INDEX"); + break; + case EX_QUALIFY: + printf("QUALIFY"); + break; + case EX_CALL: + printf("CALL"); + break; + case EX_INLINE: + printf("INLINE"); + break; + case EX_LIST: + printf("LIST"); + break; + case EX_RETURN: + printf("RETURN"); + break; + case EX_SEQUENCE: + printf("SEQUENCE"); + break; + case EX_WHILE: + printf("WHILE"); + break; + case EX_IF: + printf("IF"); + break; + case EX_ELSE: + printf("ELSE"); + break; + case EX_FOR: + printf("FOR"); + break; + case EX_DO: + printf("DO"); + break; + case EX_SCOPE: + printf("SCOPE"); + break; + case EX_BREAK: + printf("BREAK"); + break; + case EX_CONTINUE: + printf("CONTINUE"); + break; + case EX_TYPE: + printf("TYPE"); + break; + case EX_TYPECAST: + printf("TYPECAST"); + break; + case EX_LOGICAL_AND: + printf("AND"); + break; + case EX_LOGICAL_OR: + printf("OR"); + break; + case EX_LOGICAL_NOT: + printf("NOT"); + break; + case EX_ASSEMBLER: + printf("ASSEMBLER"); + break; + case EX_UNDEFINED: + printf("UNDEFINED"); + break; + case EX_SWITCH: + printf("SWITCH"); + break; + case EX_CASE: + printf("CASE"); + break; + case EX_DEFAULT: + printf("DEFAULT"); + break; + case EX_CONDITIONAL: + printf("COND"); + break; + case EX_ASSUME: + printf("ASSUME"); + break; + case EX_BANKOF: + printf("BANKOF"); + break; + case EX_CONSTRUCT: + printf("CONSTRUCT"); + break; + case EX_CLEANUP: + printf("CLEANUP"); + break; + } + printf("\n"); + + if (mLeft) + mLeft->Dump(ident + 1); + if (mRight) + mRight->Dump(ident + 1); +} + bool Expression::HasSideEffects(void) const { switch (mType) @@ -635,8 +777,8 @@ Expression* Expression::ConstantFold(Errors * errors) Declaration::Declaration(const Location& loc, DecType type) : mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr), mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), - mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mConst(nullptr), - mConstructor(nullptr), mDestructor(nullptr), + mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), mConst(nullptr), + mConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1), mCompilerOptions(0), mUseCount(0) @@ -653,6 +795,18 @@ int Declaration::Stride(void) const return mStride > 0 ? mStride : mBase->mSize; } +Declaration* Declaration::Last(void) +{ + mPrev = nullptr; + Declaration* p = this; + while (p->mNext) + { + p->mNext->mPrev = p; + p = p->mNext; + } + return p; +} + Declaration* Declaration::Clone(void) { Declaration* ndec = new Declaration(mLocation, mType); @@ -945,6 +1099,8 @@ bool Declaration::IsSame(const Declaration* dec) const 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_REFERENCE) + return 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) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 91d57b2..6f49477 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -185,7 +185,8 @@ enum ExpressionType EX_CONDITIONAL, EX_ASSUME, EX_BANKOF, - EX_CONSTRUCT + EX_CONSTRUCT, + EX_CLEANUP, }; class Expression @@ -208,6 +209,8 @@ public: bool HasSideEffects(void) const; bool IsSame(const Expression* exp) const; + + void Dump(int ident) const; }; class Declaration @@ -219,7 +222,7 @@ public: Location mLocation, mEndLocation; DecType mType; Token mToken; - Declaration* mBase, *mParams, * mNext, * mConst, * mConstructor, * mDestructor; + Declaration* mBase, *mParams, * mNext, * mPrev, * mConst, * mConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment; Expression* mValue; DeclarationScope* mScope; int mOffset, mSize, mVarIndex, mNumVars, mComplexity, mLocalSize, mAlignment, mFastCallBase, mFastCallSize, mStride, mStripe; @@ -249,6 +252,7 @@ public: Declaration* ToStriped(int stripe); Declaration* ToStriped(Errors* errors); Declaration* Clone(void); + Declaration* Last(void); int Stride(void) const; }; diff --git a/oscar64/Errors.h b/oscar64/Errors.h index fb32c8b..8d7f14d 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -14,7 +14,7 @@ class Ident; enum ErrorID { EINFO_GENERIC = 1000, - + EWARN_GENERIC = 2000, EWARN_CONSTANT_TRUNCATED, EWARN_UNKNOWN_PRAGMA, @@ -78,6 +78,8 @@ enum ErrorID ERRO_NO_MATCHING_FUNCTION_CALL, ERRO_AMBIGUOUS_FUNCTION_CALL, EERR_NO_DEFAULT_CONSTRUCTOR, + EERR_INVALID_OPERATOR, + EERR_MISSING_TEMP, ERRR_STACK_OVERFLOW, ERRR_INVALID_NUMBER, diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 185b6a6..f299058 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -429,6 +429,14 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec) mFunctions.Push(dec); + Declaration* pdec = dec->mBase->mParams; + while (pdec) + { + if (pdec->mBase->mType == DT_TYPE_STRUCT && (pdec->mBase->mCopyConstructor || pdec->mBase->mDestructor)) + dec->mBase->mFlags |= DTF_STACKCALL; + pdec = pdec->mNext; + } + dec->mFlags |= DTF_ANALYZED; dec->mFlags |= DTF_FUNC_INTRSAVE; @@ -679,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 1 +#if 0 if (mCompilerOptions & COPT_OPTIMIZE_BASIC) { if (!(pdec->mFlags & DTF_FPARAM_NOCONST)) @@ -714,8 +722,14 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo } #endif } + + if (pdec && pdec->mBase->mType == DT_TYPE_STRUCT && pdec->mBase->mCopyConstructor) + { + AnalyzeProcedure(pdec->mBase->mCopyConstructor->mValue, pdec->mBase->mCopyConstructor); + RegisterCall(procDec, pdec->mBase->mCopyConstructor); + } - if (pex->mType == EX_CALL && pex->mDecType->mType == DT_TYPE_STRUCT) + if (pex->mType == EX_CALL && pex->mDecType->mType == DT_TYPE_STRUCT && !(pdec && pdec->mBase->mType == DT_TYPE_REFERENCE)) ldec->mBase->mFlags |= DTF_STACKCALL; if (pdec) @@ -734,7 +748,14 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo return Analyze(exp->mRight, procDec, false); case EX_RETURN: if (exp->mLeft) + { RegisterProc(Analyze(exp->mLeft, procDec, false)); + if (procDec->mBase->mBase && procDec->mBase->mBase->mType == DT_TYPE_STRUCT && procDec->mBase->mBase->mCopyConstructor) + { + AnalyzeProcedure(procDec->mBase->mBase->mCopyConstructor->mValue, procDec->mBase->mBase->mCopyConstructor); + RegisterCall(procDec, procDec->mBase->mBase->mCopyConstructor); + } + } break; case EX_SEQUENCE: do @@ -761,6 +782,10 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo if (exp->mLeft->mRight) Analyze(exp->mLeft->mRight, procDec, false); return Analyze(exp->mRight, procDec, false); + + case EX_CLEANUP: + Analyze(exp->mRight, procDec, false); + return Analyze(exp->mLeft, procDec, lhs); case EX_WHILE: procDec->mFlags &= ~DTF_FUNC_CONSTEXPR; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 3e8963b..9517e7d 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -16017,7 +16017,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "test_retparam_value"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 09c2406..13bd34f 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -856,14 +856,14 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e } } -void InterCodeGenerator::UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack* bottom) +void InterCodeGenerator::UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack* bottom, InlineMapper* inlineMapper) { while (stack && stack != bottom) { if (stack->mDestruct) { DestructStack* destack = nullptr; - TranslateExpression(procType, proc, block, stack->mDestruct, destack, BranchTarget(), BranchTarget(), nullptr); + TranslateExpression(procType, proc, block, stack->mDestruct, destack, BranchTarget(), BranchTarget(), inlineMapper); } stack = stack->mNext; @@ -873,7 +873,7 @@ void InterCodeGenerator::UnwindDestructStack(Declaration* procType, InterCodePro mErrors->Error(proc->mLocation, EWARN_DESTRUCTOR_MISMATCH, "Destructor sequence mismatch"); } -InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr) +InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr, ExValue* lrexp) { DestructStack* destack = nullptr; @@ -1024,13 +1024,20 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro Declaration* rdec = nullptr; if (ftype->mBase->mType != DT_TYPE_VOID) { - int nindex = proc->mNumLocals++; - nmapper.mResult = nindex; + if (lrexp) + { + nmapper.mResultExp = lrexp; + } + else + { + int nindex = proc->mNumLocals++; + nmapper.mResult = nindex; - rdec = new Declaration(ftype->mLocation, DT_VARIABLE); - rdec->mVarIndex = nindex; - rdec->mBase = ftype->mBase; - rdec->mSize = rdec->mBase->mSize; + rdec = new Declaration(ftype->mLocation, DT_VARIABLE); + rdec->mVarIndex = nindex; + rdec->mBase = ftype->mBase; + rdec->mSize = rdec->mBase->mSize; + } } vl = TranslateExpression(ftype, proc, block, fexp, destack, BranchTarget(), BranchTarget(), &nmapper); @@ -1041,6 +1048,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro block->Close(nmapper.mReturn, nullptr); block = nmapper.mReturn; + UnwindDestructStack(ftype, proc, block, destack, nullptr, &nmapper); + if (rdec) { InterInstruction* ins = new InterInstruction(exp->mLocation, IC_CONSTANT); @@ -1055,10 +1064,214 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro return ExValue(rdec->mBase, ins->mDst.mTemp, 1); } + else if (lrexp) + { + return *lrexp; + } else return ExValue(TheVoidTypeDeclaration); } +void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper) +{ + if (vl.mType->mCopyConstructor) + { + Declaration* ccdec = vl.mType->mCopyConstructor; + if (!ccdec->mLinkerObject) + this->TranslateProcedure(proc->mModule, ccdec->mValue, ccdec); + + bool canInline = (mCompilerOptions & COPT_OPTIMIZE_INLINE) && !(inlineMapper && inlineMapper->mDepth > 10); + bool doInline = false; + + if (canInline) + { + if (ccdec->mFlags & DTF_INLINE) + { + if ((ccdec->mFlags & DTF_REQUEST_INLINE) || (mCompilerOptions & COPT_OPTIMIZE_AUTO_INLINE)) + { + if (proc->mNativeProcedure || !(ccdec->mFlags & DTF_NATIVE)) + doInline = true; + } + } + } + + if (doInline) + { + DestructStack* destack = nullptr; + + Expression* fexp = ccdec->mValue; + Declaration* ftype = ccdec->mBase; + + InlineMapper nmapper; + nmapper.mReturn = new InterCodeBasicBlock(proc); + nmapper.mVarIndex = proc->mNumLocals; + nmapper.mConstExpr = false; + proc->mNumLocals += ccdec->mNumVars; + if (inlineMapper) + nmapper.mDepth = inlineMapper->mDepth + 1; + + Declaration* pdec = ftype->mParams; + int nindex = proc->mNumLocals++; + Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); + + InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + ains->mDst.mType = IT_POINTER; + ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); + ains->mConst.mMemory = IM_LOCAL; + ains->mConst.mVarIndex = nindex; + + if (!(pdec->mFlags & DTF_FPARAM_CONST)) + nmapper.mParams[pdec->mVarIndex] = nindex; + + vdec->mVarIndex = nindex; + vdec->mBase = pdec->mBase; + ains->mConst.mOperandSize = 2; + vdec->mSize = ains->mConst.mOperandSize; + vdec->mIdent = pdec->mIdent; + vdec->mQualIdent = pdec->mQualIdent; + block->Append(ains); + + InterInstruction* wins = new InterInstruction(exp->mLocation, IC_STORE); + wins->mSrc[1].mMemory = IM_INDIRECT; + wins->mSrc[0].mType = InterTypeOf(vl.mType);; + wins->mSrc[0].mTemp = vl.mTemp; + wins->mSrc[1].mType = IT_POINTER; + wins->mSrc[1].mTemp = ains->mDst.mTemp; + wins->mSrc[1].mOperandSize = 2; + if (!(pdec->mFlags & DTF_FPARAM_CONST)) + block->Append(wins); + + pdec = pdec->mNext; + + nindex = proc->mNumLocals++; + vdec = new Declaration(exp->mLocation, DT_VARIABLE); + + ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + ains->mDst.mType = IT_POINTER; + ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); + ains->mConst.mMemory = IM_LOCAL; + ains->mConst.mVarIndex = nindex; + + if (!(pdec->mFlags & DTF_FPARAM_CONST)) + nmapper.mParams[pdec->mVarIndex] = nindex; + + vdec->mVarIndex = nindex; + vdec->mBase = pdec->mBase; + ains->mConst.mOperandSize = 2; + vdec->mSize = ains->mConst.mOperandSize; + vdec->mIdent = pdec->mIdent; + vdec->mQualIdent = pdec->mQualIdent; + block->Append(ains); + + wins = new InterInstruction(exp->mLocation, IC_STORE); + wins->mSrc[1].mMemory = IM_INDIRECT; + wins->mSrc[0].mType = InterTypeOf(vr.mType);; + wins->mSrc[0].mTemp = vr.mTemp; + wins->mSrc[1].mType = IT_POINTER; + wins->mSrc[1].mTemp = ains->mDst.mTemp; + wins->mSrc[1].mOperandSize = 2; + if (!(pdec->mFlags & DTF_FPARAM_CONST)) + block->Append(wins); + + TranslateExpression(ftype, proc, block, fexp, destack, BranchTarget(), BranchTarget(), &nmapper); + + InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); + block->Append(jins); + + block->Close(nmapper.mReturn, nullptr); + block = nmapper.mReturn; + } + else if (ccdec->mBase->mFlags & DTF_FASTCALL) + { + InterInstruction* psins = new InterInstruction(exp->mLocation, IC_CONSTANT); + psins->mDst.mType = IT_POINTER; + psins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + psins->mConst.mVarIndex = 0; + psins->mConst.mIntConst = 0; + psins->mConst.mOperandSize = 2; + if (ccdec->mBase->mFlags & DTF_FASTCALL) + { + psins->mConst.mMemory = IM_FFRAME; + psins->mConst.mVarIndex += ccdec->mBase->mFastCallBase; + } + else + psins->mConst.mMemory = IM_FRAME; + block->Append(psins); + + InterInstruction* ssins = new InterInstruction(exp->mLocation, IC_STORE); + ssins->mSrc[0].mType = IT_POINTER; + ssins->mSrc[0].mTemp = vl.mTemp; + ssins->mSrc[0].mMemory = IM_INDIRECT; + ssins->mSrc[0].mOperandSize = 2; + ssins->mSrc[1] = psins->mDst; + block->Append(ssins); + + InterInstruction* plins = new InterInstruction(exp->mLocation, IC_CONSTANT); + plins->mDst.mType = IT_POINTER; + plins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + plins->mConst.mVarIndex = 2; + plins->mConst.mIntConst = 0; + plins->mConst.mOperandSize = 2; + if (ccdec->mBase->mFlags & DTF_FASTCALL) + { + plins->mConst.mMemory = IM_FFRAME; + plins->mConst.mVarIndex += ccdec->mBase->mFastCallBase; + } + else + plins->mConst.mMemory = IM_FRAME; + block->Append(plins); + + InterInstruction* slins = new InterInstruction(exp->mLocation, IC_STORE); + slins->mSrc[0].mType = IT_POINTER; + slins->mSrc[0].mTemp = vr.mTemp; + slins->mSrc[0].mMemory = IM_INDIRECT; + slins->mSrc[0].mOperandSize = 2; + slins->mSrc[1] = plins->mDst; + block->Append(slins); + + proc->AddCalledFunction(proc->mModule->mProcedures[ccdec->mVarIndex]); + + InterInstruction* pcins = new InterInstruction(exp->mLocation, IC_CONSTANT); + pcins->mDst.mType = IT_POINTER; + pcins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + pcins->mConst.mType = IT_POINTER; + pcins->mConst.mVarIndex = ccdec->mVarIndex; + pcins->mConst.mIntConst = 0; + pcins->mConst.mOperandSize = 2; + pcins->mConst.mMemory = IM_GLOBAL; + pcins->mConst.mLinkerObject = ccdec->mLinkerObject; + block->Append(pcins); + + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CALL); + if (ccdec->mFlags & DTF_NATIVE) + cins->mCode = IC_CALL_NATIVE; + else + cins->mCode = IC_CALL; + cins->mSrc[0] = pcins->mDst; + cins->mNumOperands = 1; + + block->Append(cins); + } + } + else + { + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); + cins->mSrc[0].mType = IT_POINTER; + cins->mSrc[0].mTemp = vr.mTemp; + cins->mSrc[0].mMemory = IM_INDIRECT; + cins->mSrc[0].mOperandSize = vr.mType->mSize; + cins->mSrc[0].mStride = vr.mType->mStripe; + + cins->mSrc[1].mOperandSize = vl.mType->mSize; + cins->mSrc[1].mType = IT_POINTER; + cins->mSrc[1].mTemp = vl.mTemp; + cins->mSrc[1].mMemory = IM_INDIRECT; + + cins->mConst.mOperandSize = vl.mType->mSize; + block->Append(cins); + } +} + InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, ExValue* lrexp) { Declaration* dec; @@ -1079,6 +1292,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (!exp) return ExValue(TheVoidTypeDeclaration); break; + case EX_CONSTRUCT: { if (exp->mLeft->mLeft) @@ -1095,6 +1309,14 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* exp = exp->mRight; } break; + + case EX_CLEANUP: + { + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); + return vl; + } + case EX_CONSTANT: dec = exp->mDecValue; switch (dec->mType) @@ -2510,7 +2732,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (doInline) { - return TranslateInline(procType, proc, block, exp, breakBlock, continueBlock, inlineMapper, inlineConstexpr); + return TranslateInline(procType, proc, block, exp, breakBlock, continueBlock, inlineMapper, inlineConstexpr, lrexp); } else { @@ -2659,6 +2881,31 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ExValue vp(pdec ? pdec->mBase : TheSignedIntTypeDeclaration, ains->mDst.mTemp, 1); + if (pdec && pdec->mBase->mType == DT_TYPE_REFERENCE && texp->mType == EX_CALL) + { + mErrors->Error(texp->mLocation, EERR_MISSING_TEMP, "Missing temporary variable"); +#if 0 + int nindex = proc->mNumLocals++; + + Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); + + vdec->mVarIndex = nindex; + vdec->mBase = pdec->mBase->mBase; + vdec->mSize = pdec->mBase->mBase->mSize; + + InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT); + vins->mDst.mType = IT_POINTER; + vins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + vins->mConst.mMemory = IM_LOCAL; + vins->mConst.mVarIndex = nindex; + vins->mConst.mOperandSize = vdec->mSize; + block->Append(vins); + + vp.mType = pdec->mBase->mBase; + vp.mTemp = vins->mDst.mTemp; +#endif + } + vr = TranslateExpression(procType, proc, block, texp, destack, breakBlock, continueBlock, inlineMapper, &vp); if (!(pdec && pdec->mBase->mType == DT_TYPE_REFERENCE) && (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)) @@ -2673,6 +2920,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vp.mTemp != vr.mTemp) { + CopyStruct(proc, exp, block, vp, vr, inlineMapper); +#if 0 InterInstruction* cins = new InterInstruction(texp->mLocation, IC_COPY); cins->mSrc[0].mType = IT_POINTER; cins->mSrc[0].mTemp = vr.mTemp; @@ -2687,6 +2936,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* cins->mConst.mOperandSize = vp.mType->mSize; block->Append(cins); +#endif } atotal += vr.mType->mSize; @@ -2932,21 +3182,33 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (inlineMapper) { - InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); - ains->mDst.mType = IT_POINTER; - ains->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); - ains->mConst.mOperandSize = procType->mBase->mSize; - ains->mConst.mIntConst = 0; - ains->mConst.mVarIndex = inlineMapper->mResult;; - ains->mConst.mMemory = IM_LOCAL; - block->Append(ains); + if (inlineMapper->mResultExp) + { + ins->mSrc[1].mType = IT_POINTER; + ins->mSrc[1].mTemp = inlineMapper->mResultExp->mTemp; + ins->mSrc[1].mMemory = IM_INDIRECT; + ins->mCode = IC_STORE; + ins->mSrc[1].mOperandSize = 2; + ins->mNumOperands = 2; + } + else + { + InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + ains->mDst.mType = IT_POINTER; + ains->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ains->mConst.mOperandSize = procType->mBase->mSize; + ains->mConst.mIntConst = 0; + ains->mConst.mVarIndex = inlineMapper->mResult;; + ains->mConst.mMemory = IM_LOCAL; + block->Append(ains); - ins->mSrc[1].mType = ains->mDst.mType; - ins->mSrc[1].mTemp = ains->mDst.mTemp; - ins->mSrc[1].mMemory = IM_INDIRECT; - ins->mCode = IC_STORE; - ins->mSrc[1].mOperandSize = ains->mConst.mOperandSize; - ins->mNumOperands = 2; + ins->mSrc[1].mType = ains->mDst.mType; + ins->mSrc[1].mTemp = ains->mDst.mTemp; + ins->mSrc[1].mMemory = IM_INDIRECT; + ins->mCode = IC_STORE; + ins->mSrc[1].mOperandSize = ains->mConst.mOperandSize; + ins->mNumOperands = 2; + } } else { @@ -2969,14 +3231,21 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (inlineMapper) { - 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); + 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); + } ins->mCode = IC_NONE; } @@ -3009,20 +3278,102 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ins->mCode = IC_RETURN; } - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); - cins->mSrc[0].mType = IT_POINTER; - cins->mSrc[0].mTemp = vr.mTemp; - cins->mSrc[0].mMemory = IM_INDIRECT; - cins->mSrc[0].mOperandSize = procType->mBase->mSize; - cins->mSrc[0].mStride = vr.mType->mStripe; + CopyStruct(proc, exp, block, ExValue(procType->mBase, ains->mDst.mTemp), vr, inlineMapper); +#if 0 + if (procType->mBase->mCopyConstructor) + { + Declaration* ccdec = procType->mBase->mCopyConstructor; + if (ccdec->mBase->mFlags & DTF_FASTCALL) + { + if (!ccdec->mLinkerObject) + this->TranslateProcedure(proc->mModule, ccdec->mValue, ccdec); - cins->mSrc[1].mOperandSize = procType->mBase->mSize; - cins->mSrc[1].mType = IT_POINTER; - cins->mSrc[1].mTemp = ains->mDst.mTemp; - cins->mSrc[1].mMemory = IM_INDIRECT; + InterInstruction* psins = new InterInstruction(exp->mLocation, IC_CONSTANT); + psins->mDst.mType = IT_POINTER; + psins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + psins->mConst.mVarIndex = 0; + psins->mConst.mIntConst = 0; + psins->mConst.mOperandSize = 2; + if (procType->mFlags & DTF_FASTCALL) + { + psins->mConst.mMemory = IM_FPARAM; + psins->mConst.mVarIndex += ccdec->mBase->mFastCallBase; + } + else + psins->mConst.mMemory = IM_PARAM; + block->Append(psins); - cins->mConst.mOperandSize = procType->mBase->mSize; - block->Append(cins); + InterInstruction* ssins = new InterInstruction(exp->mLocation, IC_STORE); + ssins->mSrc[0] = ains->mDst; + ssins->mSrc[1] = psins->mDst; + block->Append(ssins); + + InterInstruction* plins = new InterInstruction(exp->mLocation, IC_CONSTANT); + plins->mDst.mType = IT_POINTER; + plins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + plins->mConst.mVarIndex = 2; + plins->mConst.mIntConst = 0; + plins->mConst.mOperandSize = 2; + if (procType->mFlags & DTF_FASTCALL) + { + plins->mConst.mMemory = IM_FPARAM; + plins->mConst.mVarIndex += ccdec->mBase->mFastCallBase; + } + else + plins->mConst.mMemory = IM_PARAM; + block->Append(plins); + + InterInstruction* slins = new InterInstruction(exp->mLocation, IC_STORE); + slins->mSrc[0].mType = IT_POINTER; + slins->mSrc[0].mTemp = vr.mTemp; + slins->mSrc[0].mMemory = IM_INDIRECT; + slins->mSrc[0].mOperandSize = procType->mBase->mSize; + slins->mSrc[0].mStride = vr.mType->mStripe; + slins->mSrc[1] = plins->mDst; + block->Append(slins); + + proc->AddCalledFunction(proc->mModule->mProcedures[ccdec->mVarIndex]); + + InterInstruction* pcins = new InterInstruction(exp->mLocation, IC_CONSTANT); + pcins->mDst.mType = IT_POINTER; + pcins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + pcins->mConst.mType = IT_POINTER; + pcins->mConst.mVarIndex = ccdec->mVarIndex; + pcins->mConst.mIntConst = 0; + pcins->mConst.mOperandSize = 2; + pcins->mConst.mMemory = IM_GLOBAL; + pcins->mConst.mLinkerObject = ccdec->mLinkerObject; + block->Append(pcins); + + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CALL); + if (ccdec->mFlags & DTF_NATIVE) + cins->mCode = IC_CALL_NATIVE; + else + cins->mCode = IC_CALL; + cins->mSrc[0] = pcins->mDst; + cins->mNumOperands = 1; + + block->Append(cins); + } + } + else + { + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); + cins->mSrc[0].mType = IT_POINTER; + cins->mSrc[0].mTemp = vr.mTemp; + cins->mSrc[0].mMemory = IM_INDIRECT; + cins->mSrc[0].mOperandSize = procType->mBase->mSize; + cins->mSrc[0].mStride = vr.mType->mStripe; + + cins->mSrc[1].mOperandSize = procType->mBase->mSize; + cins->mSrc[1].mType = IT_POINTER; + cins->mSrc[1].mTemp = ains->mDst.mTemp; + cins->mSrc[1].mMemory = IM_INDIRECT; + + cins->mConst.mOperandSize = procType->mBase->mSize; + block->Append(cins); + } +#endif } else { @@ -3040,21 +3391,33 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (inlineMapper) { - InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); - ains->mDst.mType = IT_POINTER; - ains->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); - ains->mConst.mOperandSize = procType->mBase->mSize; - ains->mConst.mIntConst = 0; - ains->mConst.mVarIndex = inlineMapper->mResult;; - ains->mConst.mMemory = IM_LOCAL; - block->Append(ains); + if (inlineMapper->mResultExp) + { + ins->mSrc[1].mType = IT_POINTER; + ins->mSrc[1].mTemp = inlineMapper->mResultExp->mTemp; + ins->mSrc[1].mMemory = IM_INDIRECT; + ins->mCode = IC_STORE; + ins->mSrc[1].mOperandSize = procType->mBase->mSize; + ins->mNumOperands = 2; + } + else + { + InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + ains->mDst.mType = IT_POINTER; + ains->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ains->mConst.mOperandSize = procType->mBase->mSize; + ains->mConst.mIntConst = 0; + ains->mConst.mVarIndex = inlineMapper->mResult;; + ains->mConst.mMemory = IM_LOCAL; + block->Append(ains); - ins->mSrc[1].mType = ains->mDst.mType; - ins->mSrc[1].mTemp = ains->mDst.mTemp; - ins->mSrc[1].mMemory = IM_INDIRECT; - ins->mCode = IC_STORE; - ins->mSrc[1].mOperandSize = ains->mConst.mOperandSize; - ins->mNumOperands = 2; + ins->mSrc[1].mType = ains->mDst.mType; + ins->mSrc[1].mTemp = ains->mDst.mTemp; + ins->mSrc[1].mMemory = IM_INDIRECT; + ins->mCode = IC_STORE; + ins->mSrc[1].mOperandSize = ains->mConst.mOperandSize; + ins->mNumOperands = 2; + } } else { @@ -3075,7 +3438,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ins->mCode = IC_RETURN; } - UnwindDestructStack(procType, proc, block, destack, nullptr); + UnwindDestructStack(procType, proc, block, destack, nullptr, inlineMapper); if (ins->mCode != IC_NONE) block->Append(ins); @@ -3097,7 +3460,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { if (breakBlock.mBlock) { - UnwindDestructStack(procType, proc, block, destack, breakBlock.mStack); + UnwindDestructStack(procType, proc, block, destack, breakBlock.mStack, inlineMapper); InterInstruction * jins = new InterInstruction(exp->mLocation, IC_JUMP); block->Append(jins); @@ -3114,7 +3477,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { if (continueBlock.mBlock) { - UnwindDestructStack(procType, proc, block, destack, continueBlock.mStack); + UnwindDestructStack(procType, proc, block, destack, continueBlock.mStack, inlineMapper); InterInstruction * jins = new InterInstruction(exp->mLocation, IC_JUMP); block->Append(jins); @@ -3508,7 +3871,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); - UnwindDestructStack(procType, proc, block, destack, odestack); + UnwindDestructStack(procType, proc, block, destack, odestack, inlineMapper); destack = odestack; return ExValue(TheVoidTypeDeclaration); @@ -3536,7 +3899,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vr = TranslateExpression(procType, proc, bblock, exp->mRight, destack, BranchTarget(eblock, odestack), BranchTarget(lblock, idestack), inlineMapper); - UnwindDestructStack(procType, proc, bblock, destack, idestack); + UnwindDestructStack(procType, proc, bblock, destack, idestack, inlineMapper); destack = idestack; bblock->Append(jins1); @@ -3544,7 +3907,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* block = eblock; - UnwindDestructStack(procType, proc, block, destack, odestack); + UnwindDestructStack(procType, proc, block, destack, odestack, inlineMapper); destack = odestack; return ExValue(TheVoidTypeDeclaration); @@ -3565,7 +3928,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* DestructStack* itdestack = destack; vr = TranslateExpression(procType, proc, tblock, exp->mRight->mLeft, destack, breakBlock, continueBlock, inlineMapper); - UnwindDestructStack(procType, proc, tblock, destack, itdestack); + UnwindDestructStack(procType, proc, tblock, destack, itdestack, inlineMapper); destack = itdestack; tblock->Append(jins0); @@ -3575,7 +3938,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { DestructStack* ifdestack = destack; vr = TranslateExpression(procType, proc, fblock, exp->mRight->mRight, destack, breakBlock, continueBlock, inlineMapper); - UnwindDestructStack(procType, proc, fblock, destack, ifdestack); + UnwindDestructStack(procType, proc, fblock, destack, ifdestack, inlineMapper); destack = ifdestack; } fblock->Append(jins1); @@ -3583,7 +3946,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* block = eblock; - UnwindDestructStack(procType, proc, block, destack, odestack); + UnwindDestructStack(procType, proc, block, destack, odestack, inlineMapper); destack = odestack; return ExValue(TheVoidTypeDeclaration); @@ -3626,7 +3989,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vr = TranslateExpression(procType, proc, bblock, exp->mRight, destack, BranchTarget(eblock, odestack), BranchTarget(iblock, idestack), inlineMapper); - UnwindDestructStack(procType, proc, bblock, destack, idestack); + UnwindDestructStack(procType, proc, bblock, destack, idestack, inlineMapper); destack = idestack; bblock->Append(jins2); @@ -3641,7 +4004,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* block = eblock; - UnwindDestructStack(procType, proc, block, destack, odestack); + UnwindDestructStack(procType, proc, block, destack, odestack, inlineMapper); destack = odestack; return ExValue(TheVoidTypeDeclaration); @@ -3664,14 +4027,14 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vr = TranslateExpression(procType, proc, cblock, exp->mRight, destack, BranchTarget(eblock, odestack), BranchTarget(cblock, idestack), inlineMapper); - UnwindDestructStack(procType, proc, cblock, destack, idestack); + UnwindDestructStack(procType, proc, cblock, destack, idestack, inlineMapper); destack = idestack; TranslateLogic(procType, proc, cblock, lblock, eblock, exp->mLeft, destack, inlineMapper); block = eblock; - UnwindDestructStack(procType, proc, block, destack, odestack); + UnwindDestructStack(procType, proc, block, destack, odestack, inlineMapper); destack = odestack; return ExValue(TheVoidTypeDeclaration); @@ -3759,7 +4122,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (block) { - UnwindDestructStack(procType, proc, block, destack, odestack); + UnwindDestructStack(procType, proc, block, destack, odestack, inlineMapper); InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); @@ -3962,6 +4325,11 @@ 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, "test_retparam_value")) + exp->Dump(0); +#endif + uint64 outerCompilerOptions = mCompilerOptions; mCompilerOptions = dec->mCompilerOptions; @@ -4050,7 +4418,7 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod TranslateExpression(dec->mBase, proc, exitBlock, exp, destack, BranchTarget(), BranchTarget(), nullptr); - UnwindDestructStack(dec->mBase, proc, exitBlock, destack, nullptr); + UnwindDestructStack(dec->mBase, proc, exitBlock, destack, nullptr, nullptr); } else mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->mQualIdent->mString); diff --git a/oscar64/InterCodeGenerator.h b/oscar64/InterCodeGenerator.h index 8a768d8..4088beb 100644 --- a/oscar64/InterCodeGenerator.h +++ b/oscar64/InterCodeGenerator.h @@ -59,9 +59,10 @@ protected: InterCodeBasicBlock * mReturn; int mResult, mDepth, mVarIndex; bool mConstExpr; + ExValue * mResultExp; InlineMapper(void) - : mParams(-1), mResult(-1), mDepth(0) + : mParams(-1), mResult(-1), mDepth(0), mResultExp(nullptr) {} }; @@ -79,8 +80,9 @@ protected: ExValue CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, Declaration * type, bool checkTrunc = true); ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, const BranchTarget & breakBlock, const BranchTarget& continueBlock, InlineMapper * inlineMapper, ExValue * lrexp = nullptr); void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, DestructStack*& destack, InlineMapper* inlineMapper); - ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr); + ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr, ExValue* lrexp); + void CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper); - void UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack * bottom); + void UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack * bottom, InlineMapper* inlineMapper); void BuildInitializer(InterCodeModule* mod, uint8 * dp, int offset, Declaration* data, InterVariable * variable); }; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index d245355..2226e4e 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -34621,6 +34621,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; progress = true; } + else if ( mIns[i + 0].mType == ASMIT_INX && mIns[i + 1].mType == ASMIT_DEX && !(mIns[i + 1].mLive & LIVE_CPU_REG_Z)) @@ -34654,6 +34655,39 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass progress = true; } + else if ( + mIns[i + 0].mType == ASMIT_LDX && mIns[i + 0].mMode == ASMIM_IMMEDIATE && + mIns[i + 1].mType == ASMIT_DEX) + { + mIns[i + 0].mAddress = (mIns[i + 0].mAddress - 1) & 255; + mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + progress = true; + } + else if ( + mIns[i + 0].mType == ASMIT_LDX && mIns[i + 0].mMode == ASMIM_IMMEDIATE && + mIns[i + 1].mType == ASMIT_INX) + { + mIns[i + 0].mAddress = (mIns[i + 0].mAddress + 1) & 255; + mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + progress = true; + } + else if ( + mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && + mIns[i + 1].mType == ASMIT_DEY) + { + mIns[i + 0].mAddress = (mIns[i + 0].mAddress - 1) & 255; + mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + progress = true; + } + else if ( + mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && + mIns[i + 1].mType == ASMIT_INY) + { + mIns[i + 0].mAddress = (mIns[i + 0].mAddress + 1) & 255; + mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + progress = true; + } + else if ( mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_IMMEDIATE || mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE || mIns[i + 0].mMode == ASMIM_ABSOLUTE_X) && mIns[i + 1].mType == ASMIT_TAY && !(mIns[i + 1].mLive & LIVE_CPU_REG_A)) @@ -34952,7 +34986,10 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass if (FindPageStartAddress(i, mIns[i + 1].mAddress, addr)) { if (mIns[i + 1].mLive & LIVE_CPU_REG_Y) + { mIns.Insert(i + 2, mIns[i + 0]); + mIns[i + 2].mLive |= mIns[i + 1].mLive; + } int absaddr = addr + mIns[i + 0].mAddress; @@ -39997,7 +40034,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "mapTimeTick"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "Y::Y"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -41273,7 +41310,6 @@ void NativeCodeProcedure::Optimize(void) } while (changed); - #if 1 ResetVisited(); mEntryBlock->ReduceLocalYPressure(); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 3bf165a..7ac9e9c 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -205,6 +205,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) if (mCompilerOptions & COPT_CPLUSPLUS) { + AddDefaultConstructors(pthis); + Declaration* cdec = pthis->mBase->mConstructor; while (cdec) { @@ -1225,60 +1227,64 @@ void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) thisexp->mLeft = pthisexp; Declaration* dec = pthis->mBase->mParams; - while (dec) + if (dec) { - if (dec->mType == DT_ELEMENT) + dec = dec->Last(); + while (dec) { - Declaration* mfunc = cfunc->mScope ? cfunc->mScope->Lookup(dec->mIdent) : nullptr; - - if (mfunc) + if (dec->mType == DT_ELEMENT) { - Expression* sexp = new Expression(cfunc->mLocation, EX_SEQUENCE); - sexp->mLeft = mfunc->mValue; - sexp->mRight = cfunc->mValue; - cfunc->mValue = sexp; - } - else if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mConstructor) - { - Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); - qexp->mLeft = thisexp; - qexp->mDecValue = dec; - qexp->mDecType = dec->mBase; + Declaration* mfunc = cfunc->mScope ? cfunc->mScope->Lookup(dec->mIdent) : nullptr; - Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); - pexp->mLeft = qexp; - pexp->mToken = TK_BINARY_AND; - pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); - pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - pexp->mDecType->mBase = dec->mBase; - pexp->mDecType->mSize = 2; - - Declaration* mdec = dec->mBase->mConstructor; - while (mdec && mdec->mBase->mParams->mNext) - mdec = mdec->mNext; - - Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); - if (mdec) + if (mfunc) { - cexp->mDecValue = mdec; - cexp->mDecType = cexp->mDecValue->mBase; + Expression* sexp = new Expression(cfunc->mLocation, EX_SEQUENCE); + sexp->mLeft = mfunc->mValue; + sexp->mRight = cfunc->mValue; + cfunc->mValue = sexp; } - else - mErrors->Error(dec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor"); + else if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mConstructor) + { + Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); + qexp->mLeft = thisexp; + qexp->mDecValue = dec; + qexp->mDecType = dec->mBase; - Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = pexp; + Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); + pexp->mLeft = qexp; + pexp->mToken = TK_BINARY_AND; + pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + pexp->mDecType->mBase = dec->mBase; + pexp->mDecType->mSize = 2; - Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + Declaration* mdec = dec->mBase->mConstructor; + while (mdec && mdec->mBase->mParams->mNext) + mdec = mdec->mNext; - sexp->mLeft = dexp; - sexp->mRight = cfunc->mValue; - cfunc->mValue = sexp; + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + if (mdec) + { + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + } + else + mErrors->Error(dec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor"); + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + + sexp->mLeft = dexp; + sexp->mRight = cfunc->mValue; + cfunc->mValue = sexp; + } } - } - dec = dec->mNext; + dec = dec->mPrev; + } } } @@ -1339,29 +1345,32 @@ void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc) mThisPointer = othis; } -void Parser::AppendMemberDestructor(Declaration* pthis) +void Parser::AddDefaultConstructors(Declaration* pthis) { - bool needDestructor = !pthis->mBase->mDestructor; + bool simpleDestructor = true, simpleAssignment = true; Declaration* dec = pthis->mBase->mParams; - while (!needDestructor && dec) + while (dec) { - if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mDestructor) + if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT) { - needDestructor = true; - break; + if (dec->mBase->mDestructor) + simpleDestructor = false; + if (dec->mBase->mCopyAssignment) + simpleAssignment = false; } dec = dec->mNext; } - if (needDestructor) + if (!simpleDestructor) { if (!pthis->mBase->mDestructor) { - Declaration* ctdec = ParseFunctionDeclaration(TheVoidTypeDeclaration); - - if (ctdec->mParams) - mErrors->Error(ctdec->mLocation, EERR_WRONG_PARAMETER, "Destructor can't have parameter"); + Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); + ctdec->mSize = 0; + Declaration* pdec = nullptr; + ctdec->mBase = TheVoidTypeDeclaration; + ctdec->mFlags |= DTF_DEFINED; PrependThisArgument(ctdec, pthis); @@ -1376,10 +1385,7 @@ void Parser::AppendMemberDestructor(Declaration* pthis) if (mCompilerOptions & COPT_NATIVE) cdec->mFlags |= DTF_NATIVE; - if (pthis->mBase->mDestructor) - mErrors->Error(ctdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate destrcutor definition"); - else - pthis->mBase->mDestructor = cdec; + pthis->mBase->mDestructor = cdec; char dname[100]; strcpy_s(dname, "~"); @@ -1394,8 +1400,319 @@ void Parser::AppendMemberDestructor(Declaration* pthis) cdec->mFlags |= DTF_DEFINED; cdec->mNumVars = mLocalIndex; + + cdec->mValue = new Expression(mScanner->mLocation, EX_VOID); } + if (!pthis->mBase->mConstructor) + { + Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); + ctdec->mSize = 0; + Declaration* pdec = nullptr; + ctdec->mBase = TheVoidTypeDeclaration; + ctdec->mFlags |= DTF_DEFINED; + + PrependThisArgument(ctdec, pthis); + + Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); + cdec->mBase = ctdec; + + cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; + + cdec->mSection = mCodeSection; + + if (mCompilerOptions & COPT_NATIVE) + cdec->mFlags |= DTF_NATIVE; + + pthis->mBase->mConstructor = cdec; + + cdec->mIdent = pthis->mBase->mIdent; + cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); + + cdec->mCompilerOptions = mCompilerOptions; + cdec->mBase->mCompilerOptions = mCompilerOptions; + + cdec->mVarIndex = -1; + + cdec->mFlags |= DTF_DEFINED; + cdec->mNumVars = mLocalIndex; + + cdec->mValue = new Expression(mScanner->mLocation, EX_VOID); + } + + if (!pthis->mBase->mCopyConstructor) + { + Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); + ctdec->mSize = 0; + ctdec->mBase = TheVoidTypeDeclaration; + ctdec->mFlags |= DTF_DEFINED; + + Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + adec->mVarIndex = 0; + adec->mOffset = 0; + adec->mBase = new Declaration(mScanner->mLocation, DT_TYPE_REFERENCE); + adec->mBase->mSize = 2; + adec->mBase->mBase = pthis->mBase; + adec->mBase->mFlags |= DTF_CONST | DTF_DEFINED; + adec->mSize = adec->mBase->mSize; + adec->mIdent = adec->mQualIdent = Ident::Unique("_"); + + ctdec->mParams = adec; + + PrependThisArgument(ctdec, pthis); + + Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); + cdec->mBase = ctdec; + + cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; + + cdec->mSection = mCodeSection; + + if (mCompilerOptions & COPT_NATIVE) + cdec->mFlags |= DTF_NATIVE; + + pthis->mBase->mCopyConstructor = cdec; + cdec->mNext = pthis->mBase->mConstructor; + pthis->mBase->mConstructor = cdec; + + cdec->mIdent = pthis->mBase->mIdent; + cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); + + cdec->mCompilerOptions = mCompilerOptions; + cdec->mBase->mCompilerOptions = mCompilerOptions; + + cdec->mVarIndex = -1; + + cdec->mValue = new Expression(mScanner->mLocation, EX_VOID); + + // Now add all the copying + + Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); + pthisexp->mDecType = pthis; + pthisexp->mDecValue = cdec->mBase->mParams; + + Expression* thisexp = new Expression(mScanner->mLocation, EX_PREFIX); + thisexp->mToken = TK_MUL; + thisexp->mDecType = pthis->mBase; + thisexp->mLeft = pthisexp; + + Expression* thatexp = new Expression(pthis->mLocation, EX_VARIABLE); + thatexp->mDecType = adec->mBase; + thatexp->mDecValue = cdec->mBase->mParams->mNext; + + cdec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS); + + Declaration* dec = pthis->mBase->mParams; + while (dec) + { + if (dec->mType == DT_ELEMENT) + { + Expression* lexp = new Expression(pthis->mLocation, EX_QUALIFY); + lexp->mLeft = thisexp; + lexp->mDecValue = dec; + lexp->mDecType = dec->mBase; + + Expression* rexp = new Expression(pthis->mLocation, EX_QUALIFY); + rexp->mLeft = thatexp; + rexp->mDecValue = dec; + rexp->mDecType = dec->mBase; + + Expression* mexp; + + if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mCopyConstructor) + { + Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); + pexp->mLeft = lexp; + pexp->mToken = TK_BINARY_AND; + pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + pexp->mDecType->mBase = dec->mBase; + pexp->mDecType->mSize = 2; + + Declaration* mdec = dec->mBase->mCopyConstructor; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + + mexp = new Expression(mScanner->mLocation, EX_CALL); + mexp->mLeft = cexp; + mexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + mexp->mRight->mLeft = pexp; + mexp->mRight->mRight = rexp; + } + else + { + mexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); + mexp->mLeft = lexp; + mexp->mRight = rexp; + mexp->mDecType = lexp->mDecType; + } + + Declaration* mcdec = new Declaration(mScanner->mLocation, DT_CONST_CONSTRUCTOR); + mcdec->mIdent = mScanner->mTokenIdent; + mcdec->mValue = mexp; + + cdec->mScope->Insert(dec->mIdent, mcdec); + } + + dec = dec->mNext; + } + + cdec->mFlags |= DTF_DEFINED; + cdec->mNumVars = mLocalIndex; + } + } + + if (!simpleAssignment) + { + // Copy assignment operator + if (!pthis->mBase->mCopyAssignment) + { + Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); + ctdec->mSize = 0; + ctdec->mBase = new Declaration(mScanner->mLocation, DT_TYPE_REFERENCE); + ctdec->mBase->mSize = 2; + ctdec->mBase->mBase = pthis->mBase; + ctdec->mBase->mFlags |= DTF_DEFINED; + ctdec->mFlags |= DTF_DEFINED; + + Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + adec->mVarIndex = 0; + adec->mOffset = 0; + adec->mBase = new Declaration(mScanner->mLocation, DT_TYPE_REFERENCE); + adec->mBase->mSize = 2; + adec->mBase->mBase = pthis->mBase; + adec->mBase->mFlags |= DTF_CONST | DTF_DEFINED; + adec->mSize = adec->mBase->mSize; + adec->mIdent = adec->mQualIdent = Ident::Unique("_"); + + ctdec->mParams = adec; + + PrependThisArgument(ctdec, pthis); + + Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); + cdec->mBase = ctdec; + + cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; + + cdec->mSection = mCodeSection; + + if (mCompilerOptions & COPT_NATIVE) + cdec->mFlags |= DTF_NATIVE; + + cdec->mIdent = Ident::Unique("operator="); + cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); + + pthis->mBase->mCopyAssignment = cdec; + Declaration* pdec = pthis->mBase->mScope->Insert(cdec->mIdent, cdec); + if (pdec) + { + cdec->mNext = pdec->mNext; + pdec->mNext = cdec; + } + + cdec->mCompilerOptions = mCompilerOptions; + cdec->mBase->mCompilerOptions = mCompilerOptions; + + cdec->mVarIndex = -1; + + Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); + pthisexp->mDecType = pthis; + pthisexp->mDecValue = cdec->mBase->mParams; + + Expression* thisexp = new Expression(mScanner->mLocation, EX_PREFIX); + thisexp->mToken = TK_MUL; + thisexp->mDecType = pthis->mBase; + thisexp->mLeft = pthisexp; + + cdec->mValue = new Expression(mScanner->mLocation, EX_RETURN); + cdec->mValue->mLeft = thisexp; + cdec->mValue->mDecType = cdec->mBase; + + // Now add all the copying + + Expression* thatexp = new Expression(pthis->mLocation, EX_VARIABLE); + thatexp->mDecType = adec->mBase; + thatexp->mDecValue = cdec->mBase->mParams->mNext; + + cdec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS); + + Declaration* dec = pthis->mBase->mParams; + if (dec) + { + dec = dec->Last(); + while (dec) + { + if (dec->mType == DT_ELEMENT) + { + Expression* lexp = new Expression(pthis->mLocation, EX_QUALIFY); + lexp->mLeft = thisexp; + lexp->mDecValue = dec; + lexp->mDecType = dec->mBase; + + Expression* rexp = new Expression(pthis->mLocation, EX_QUALIFY); + rexp->mLeft = thatexp; + rexp->mDecValue = dec; + rexp->mDecType = dec->mBase; + + Expression* mexp; + + if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mCopyAssignment) + { + Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); + pexp->mLeft = lexp; + pexp->mToken = TK_BINARY_AND; + pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + pexp->mDecType->mBase = dec->mBase; + pexp->mDecType->mSize = 2; + + Declaration* mdec = dec->mBase->mCopyAssignment; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + + mexp = new Expression(mScanner->mLocation, EX_CALL); + mexp->mLeft = cexp; + mexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + mexp->mRight->mLeft = pexp; + mexp->mRight->mRight = rexp; + } + else + { + mexp = new Expression(mScanner->mLocation, EX_ASSIGNMENT); + mexp->mToken = TK_ASSIGN; + mexp->mLeft = lexp; + mexp->mRight = rexp; + mexp->mDecType = lexp->mDecType; + } + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + sexp->mLeft = mexp; + sexp->mRight = cdec->mValue; + cdec->mValue = sexp; + } + + dec = dec->mPrev; + } + } + + cdec->mFlags |= DTF_DEFINED; + cdec->mNumVars = mLocalIndex; + + } + } +} + +void Parser::AppendMemberDestructor(Declaration* pthis) +{ + if (pthis->mBase->mDestructor) + { if (pthis->mBase->mDestructor->mFlags & DTF_DEFINED) { Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); @@ -1407,41 +1724,45 @@ void Parser::AppendMemberDestructor(Declaration* pthis) thisexp->mDecType = pthis->mBase; thisexp->mLeft = pthisexp; - dec = pthis->mBase->mParams; - while (dec) + Declaration * dec = pthis->mBase->mParams; + if (dec) { - if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mDestructor) + dec = dec->Last(); + while (dec) { - Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); - qexp->mLeft = thisexp; - qexp->mDecValue = dec; - qexp->mDecType = dec->mBase; + if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mDestructor) + { + Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); + qexp->mLeft = thisexp; + qexp->mDecValue = dec; + qexp->mDecType = dec->mBase; - Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); - pexp->mLeft = qexp; - pexp->mToken = TK_BINARY_AND; - pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); - pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - pexp->mDecType->mBase = dec->mBase; - pexp->mDecType->mSize = 2; + Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); + pexp->mLeft = qexp; + pexp->mToken = TK_BINARY_AND; + pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + pexp->mDecType->mBase = dec->mBase; + pexp->mDecType->mSize = 2; - Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); - cexp->mDecValue = dec->mBase->mDestructor; - cexp->mDecType = cexp->mDecValue->mBase; + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = dec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; - Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = pexp; + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; - Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); - sexp->mLeft = pthis->mBase->mDestructor->mValue; - sexp->mRight = dexp; + sexp->mLeft = pthis->mBase->mDestructor->mValue; + sexp->mRight = dexp; - pthis->mBase->mDestructor->mValue = sexp; + pthis->mBase->mDestructor->mValue = sexp; + } + + dec = dec->mPrev; } - - dec = dec->mNext; } } } @@ -1470,6 +1791,208 @@ void Parser::PrependThisArgument(Declaration* fdec, Declaration* pthis) fdec->mFlags |= DTF_FUNC_THIS; } +static Expression* ConcatExpression(Expression* e1, Expression* e2) +{ + if (e1) + { + if (e2) + { + Expression* seq = new Expression(e1->mLocation, EX_SEQUENCE); + seq->mLeft = e1; + seq->mRight = e2; + return seq; + } + return e1; + } + else + return e2; +} + +Expression* Parser::CleanupExpression(Expression* exp) +{ + if (exp) + { + Expression* xexp = AddFunctionCallRefReturned(exp); + if (xexp) + { + Expression* cexp = new Expression(exp->mLocation, EX_CLEANUP); + cexp->mLeft = exp; + cexp->mRight = xexp; + return cexp; + } + } + return exp; +} + +Expression* Parser::AddFunctionCallRefReturned(Expression* exp) +{ + Expression* lexp = nullptr, * rexp = nullptr; + + if (exp->mType == EX_CALL) + { + lexp = AddFunctionCallRefReturned(exp->mLeft); + if (exp->mRight) + { + Declaration* pdec = exp->mLeft->mDecType->mParams; + Expression* rex = exp->mRight; + + while (pdec && rex) + { + Expression* pex = rex->mType == EX_LIST ? rex->mLeft : rex; + if (rex->mType == EX_LIST) + rex = rex->mRight; + else + rex = nullptr; + + rexp = ConcatExpression(rexp, AddFunctionCallRefReturned(pex)); + + if (pdec->mBase->mType == DT_TYPE_REFERENCE && pex->mDecType->mType != DT_TYPE_REFERENCE && pex->mType == EX_CALL) + { + // Returning a value object for pass as reference + // add a temporary variable + + int nindex = mLocalIndex++; + + Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); + + vdec->mVarIndex = nindex; + vdec->mBase = pdec->mBase->mBase; + vdec->mSize = pdec->mBase->mBase->mSize; + + Expression* vexp = new Expression(pex->mLocation, EX_VARIABLE); + vexp->mDecType = pdec->mBase->mBase; + vexp->mDecValue = vdec; + + Expression* cexp = new Expression(pex->mLocation, pex->mType); + cexp->mDecType = pex->mDecType; + cexp->mDecValue = pex->mDecValue; + cexp->mLeft = pex->mLeft; + cexp->mRight = pex->mRight; + cexp->mToken = pex->mToken; + + pex->mType = EX_INITIALIZATION; + pex->mLeft = vexp; + pex->mRight = cexp; + pex->mDecValue = nullptr; + pex->mDecType = vdec->mBase; + + if (vdec->mBase->mDestructor) + { + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = vdec->mBase; + texp->mDecType->mSize = 2; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = vdec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression * dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + + rexp = ConcatExpression(rexp, dexp); + } + } + + pdec = pdec->mNext; + } + } + } + else + { + if (exp->mLeft) + lexp = AddFunctionCallRefReturned(exp->mLeft); + if (exp->mRight) + rexp = AddFunctionCallRefReturned(exp->mRight); + } + + return ConcatExpression(lexp, rexp); +} + +void Parser::ParseVariableInit(Declaration* ndec) +{ + Expression* pexp = nullptr; + + mScanner->NextToken(); + if (mScanner->mToken != TK_CLOSE_PARENTHESIS) + { + pexp = ParseListExpression(); + ConsumeToken(TK_CLOSE_PARENTHESIS); + } + else + mScanner->NextToken(); + + if (pexp && pexp->mType != EX_LIST && ndec->mBase->CanAssign(pexp->mDecType)) + { + ndec->mValue = pexp; + } + else if (ndec->mBase->mConstructor) + { + Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); + vexp->mDecType = ndec->mBase; + vexp->mDecValue = ndec; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = ndec->mBase->mConstructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); + fexp->mLeft = cexp; + fexp->mRight = pexp; + + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = ndec->mBase; + texp->mDecType->mSize = 2; + + if (fexp->mRight) + { + Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = fexp->mRight; + fexp->mRight = lexp; + } + else + fexp->mRight = texp; + + ResolveOverloadCall(cexp, fexp->mRight); + + Expression* dexp = nullptr; + if (ndec->mBase->mDestructor) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = ndec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + } + + Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = fexp; + nexp->mLeft->mRight = dexp; + + nexp->mRight = vexp; + nexp->mDecType = vexp->mDecType; + + ndec->mValue = nexp; + } + else + { + ndec->mValue = pexp; + } +} + Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool expression, Declaration* pthis) { bool definingType = false, destructor = false; @@ -1658,9 +2181,14 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex { Declaration* ctdec = ParseFunctionDeclaration(TheVoidTypeDeclaration); + Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); + + if (ctdec->mParams && !ctdec->mParams->mNext && ctdec->mParams->mBase->mType == DT_TYPE_REFERENCE && + pthis->mBase->IsConstSame(ctdec->mParams->mBase->mBase)) + pthis->mBase->mCopyConstructor = cdec; + PrependThisArgument(ctdec, pthis); - Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); @@ -1763,6 +2291,8 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (cdec) { + cdec->mFlags |= storageFlags & DTF_REQUEST_INLINE; + // Initializer list if (mScanner->mToken == TK_COLON) { @@ -1814,6 +2344,8 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (bdec->mDestructor) { + bdec->mDestructor->mFlags |= storageFlags & DTF_REQUEST_INLINE; + Declaration* bthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); bthis->mFlags |= DTF_CONST | DTF_DEFINED; bthis->mBase = bdec; @@ -1880,7 +2412,16 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex { if (ndec->mBase->mType == DT_TYPE_FUNCTION && pthis) { + if (ndec->mIdent == Ident::Unique("operator==")) + { + if (ndec->mBase->mParams && ndec->mBase->mParams->mBase->mType == DT_TYPE_REFERENCE && ndec->mBase->mParams->mBase->mBase->IsSame(pthis->mBase)) + { + pthis->mBase->mCopyAssignment = ndec; + } + } + PrependThisArgument(ndec->mBase, pthis); + } if (variable) @@ -2072,74 +2613,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } else if (mScanner->mToken == TK_OPEN_PARENTHESIS && (mCompilerOptions & COPT_CPLUSPLUS)) { - if (ndec->mBase->mConstructor) - { - Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); - vexp->mDecType = ndec->mBase; - vexp->mDecValue = ndec; - - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = ndec->mBase->mConstructor; - cexp->mDecType = cexp->mDecValue->mBase; - - Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); - fexp->mLeft = cexp; - - mScanner->NextToken(); - if (mScanner->mToken != TK_CLOSE_PARENTHESIS) - { - fexp->mRight = ParseListExpression(); - ConsumeToken(TK_CLOSE_PARENTHESIS); - } - else - { - fexp->mRight = nullptr; - mScanner->NextToken(); - } - - Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); - texp->mToken = TK_BINARY_AND; - texp->mLeft = vexp; - texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); - texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = ndec->mBase; - texp->mDecType->mSize = 2; - - if (fexp->mRight) - { - Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); - lexp->mLeft = texp; - lexp->mRight = fexp->mRight; - fexp->mRight = lexp; - } - else - fexp->mRight = texp; - - ResolveOverloadCall(cexp, fexp->mRight); - - Expression* dexp = nullptr; - if (ndec->mBase->mDestructor) - { - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = ndec->mBase->mDestructor; - cexp->mDecType = cexp->mDecValue->mBase; - - dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = texp; - } - - Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); - - nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); - nexp->mLeft->mLeft = fexp; - nexp->mLeft->mRight = dexp; - - nexp->mRight = vexp; - nexp->mDecType = vexp->mDecType; - - ndec->mValue = nexp; - } + ParseVariableInit(ndec); } else if ((mCompilerOptions & COPT_CPLUSPLUS) && ndec->mBase->mConstructor && ndec->mType == DT_VARIABLE && !pthis) { @@ -2269,6 +2743,63 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec) vdec->mDecValue = dec; } } + else if ((mCompilerOptions & COPT_CPLUSPLUS) && dec->mBase->mDestructor) + { + Expression* vexp = new Expression(pdec->mLocation, EX_VARIABLE); + vexp->mDecType = dec->mBase; + vexp->mDecValue = dec; + + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = pdec->mBase; + texp->mDecType->mSize = 2; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = dec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + + Expression* aexp; + + if (dec->mBase->mCopyConstructor && !(dec->mValue->mType == EX_CALL && dec->mValue->mDecType->mType == DT_TYPE_STRUCT)) + { + Declaration* mdec = dec->mBase->mCopyConstructor; + + Expression* cexp = new Expression(dec->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + + aexp = new Expression(mScanner->mLocation, EX_CALL); + aexp->mLeft = cexp; + aexp->mRight = new Expression(dec->mLocation, EX_LIST); + aexp->mRight->mLeft = texp; + aexp->mRight->mRight = dec->mValue; + } + else + { + aexp = new Expression(dec->mValue->mLocation, EX_INITIALIZATION); + aexp->mToken = TK_ASSIGN; + aexp->mLeft = new Expression(dec->mLocation, EX_VARIABLE); + aexp->mLeft->mDecValue = dec; + aexp->mLeft->mDecType = dec->mBase; + aexp->mDecType = aexp->mLeft->mDecType; + aexp->mRight = dec->mValue; + } + + nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = aexp; + nexp->mLeft->mRight = dexp; + nexp->mRight = vexp; + nexp->mDecType = vexp->mDecType; + } else { nexp = new Expression(dec->mValue->mLocation, EX_INITIALIZATION); @@ -2914,7 +3445,23 @@ Expression* Parser::ParsePostfixExpression(bool lhs) { if (exp->mType == EX_TYPE) { - if (exp->mDecType->mConstructor) + Expression * pexp = nullptr; + + mScanner->NextToken(); + if (mScanner->mToken != TK_CLOSE_PARENTHESIS) + { + pexp = ParseListExpression(); + ConsumeToken(TK_CLOSE_PARENTHESIS); + } + else + mScanner->NextToken(); + + if (pexp && pexp->mType != EX_LIST && pexp->mDecType->IsSame(exp->mDecType)) + { + // Simple copy + exp = pexp; + } + else if (exp->mDecType->mConstructor) { Declaration* tdec = new Declaration(mScanner->mLocation, DT_VARIABLE); @@ -2934,17 +3481,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); fexp->mLeft = cexp; - mScanner->NextToken(); - if (mScanner->mToken != TK_CLOSE_PARENTHESIS) - { - fexp->mRight = ParseListExpression(); - ConsumeToken(TK_CLOSE_PARENTHESIS); - } - else - { - fexp->mRight = nullptr; - mScanner->NextToken(); - } + fexp->mRight = pexp; Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); texp->mToken = TK_BINARY_AND; @@ -2994,9 +3531,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST); nexp->mDecType = exp->mDecType; nexp->mLeft = exp; - mScanner->NextToken(); - nexp->mRight = ParseListExpression(); - ConsumeToken(TK_CLOSE_PARENTHESIS); + nexp->mRight = pexp; exp = nexp->ConstantFold(mErrors); } } @@ -3414,6 +3949,55 @@ Expression* Parser::ParseParenthesisExpression(void) return exp; } +Expression* Parser::CheckOperatorOverload(Expression* exp) +{ + if (mCompilerOptions & COPT_CPLUSPLUS) + { + if (exp->mType == EX_ASSIGNMENT) + { + Declaration* tdec = exp->mLeft->mDecType; + if (tdec->mType == DT_TYPE_STRUCT) + { + if (exp->mToken == TK_ASSIGN) + { + Declaration* mdec = tdec->mScope->Lookup(Ident::Unique("operator=")); + if (mdec) + { + Expression * nexp = new Expression(mScanner->mLocation, EX_CALL); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); + nexp->mLeft->mDecType = mdec->mBase; + nexp->mLeft->mDecValue = mdec; + + nexp->mDecType = mdec->mBase; + nexp->mRight = exp->mRight; + + Expression* texp = new Expression(nexp->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = exp->mLeft; + texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = exp->mDecType; + texp->mDecType->mSize = 2; + + Expression* lexp = new Expression(nexp->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = nexp->mRight; + nexp->mRight = lexp; + + ResolveOverloadCall(nexp->mLeft, nexp->mRight); + nexp->mDecType = nexp->mLeft->mDecType->mBase; + + exp = nexp; + } + } + } + } + } + + return exp; +} + Expression* Parser::ParseAssignmentExpression(bool lhs) { Expression* exp = ParseConditionalExpression(lhs); @@ -3426,7 +4010,9 @@ Expression* Parser::ParseAssignmentExpression(bool lhs) mScanner->NextToken(); nexp->mRight = ParseAssignmentExpression(false); nexp->mDecType = exp->mDecType; - exp = nexp; + + exp = CheckOperatorOverload(nexp); + assert(exp->mDecType); } @@ -3475,6 +4061,53 @@ Expression* Parser::ParseFunction(Declaration * dec) Expression * exp = ParseStatement(); + if (mCompilerOptions & COPT_CPLUSPLUS) + { + // Add destructors for parameters + Declaration* pdec = dec->mParams; + + while (pdec) + { + if (pdec->mBase->mType == DT_TYPE_STRUCT && pdec->mBase->mDestructor) + { + Expression* vexp = new Expression(pdec->mLocation, EX_VARIABLE); + vexp->mDecType = pdec->mBase; + vexp->mDecValue = pdec; + + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = pdec->mBase; + texp->mDecType->mSize = 2; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = pdec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression * dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + + Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = nullptr; + nexp->mLeft->mRight = dexp; + nexp->mRight = vexp; + nexp->mDecType = vexp->mDecType; + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + sexp->mLeft = nexp; + sexp->mRight = exp; + exp = sexp; + } + + pdec = pdec->mNext; + } + } + mScope->End(mScanner->mLocation); mScope = mScope->mParent; @@ -3552,7 +4185,7 @@ Expression* Parser::ParseStatement(void) case TK_IF: mScanner->NextToken(); exp = new Expression(mScanner->mLocation, EX_IF); - exp->mLeft = ParseParenthesisExpression(); + exp->mLeft = CleanupExpression(ParseParenthesisExpression()); exp->mRight = new Expression(mScanner->mLocation, EX_ELSE); exp->mRight->mLeft = ParseStatement(); if (mScanner->mToken == TK_ELSE) @@ -3571,7 +4204,7 @@ Expression* Parser::ParseStatement(void) mScope = scope; exp = new Expression(mScanner->mLocation, EX_WHILE); - exp->mLeft = ParseParenthesisExpression(); + exp->mLeft = CleanupExpression(ParseParenthesisExpression()); exp->mRight = ParseStatement(); mScope->End(mScanner->mLocation); @@ -3585,7 +4218,7 @@ Expression* Parser::ParseStatement(void) if (mScanner->mToken == TK_WHILE) { mScanner->NextToken(); - exp->mLeft = ParseParenthesisExpression(); + exp->mLeft = CleanupExpression(ParseParenthesisExpression()); ConsumeToken(TK_SEMICOLON); } else @@ -3611,7 +4244,7 @@ Expression* Parser::ParseStatement(void) // Assignment if (mScanner->mToken != TK_SEMICOLON) - initExp = ParseExpression(true); + initExp = CleanupExpression(ParseExpression(true)); if (mScanner->mToken == TK_SEMICOLON) mScanner->NextToken(); else @@ -3619,7 +4252,7 @@ Expression* Parser::ParseStatement(void) // Condition if (mScanner->mToken != TK_SEMICOLON) - conditionExp = ParseExpression(false); + conditionExp = CleanupExpression(ParseExpression(false)); if (mScanner->mToken == TK_SEMICOLON) mScanner->NextToken(); @@ -3628,7 +4261,7 @@ Expression* Parser::ParseStatement(void) // Iteration if (mScanner->mToken != TK_CLOSE_PARENTHESIS) - iterateExp = ParseExpression(false); + iterateExp = CleanupExpression(ParseExpression(false)); if (mScanner->mToken == TK_CLOSE_PARENTHESIS) mScanner->NextToken(); else @@ -3804,7 +4437,7 @@ Expression* Parser::ParseStatement(void) mScanner->NextToken(); exp = new Expression(mScanner->mLocation, EX_RETURN); if (mScanner->mToken != TK_SEMICOLON) - exp->mLeft = ParseRExpression(); + exp->mLeft = CleanupExpression(ParseRExpression()); ConsumeToken(TK_SEMICOLON); break; case TK_BREAK: @@ -3846,7 +4479,7 @@ Expression* Parser::ParseStatement(void) break; default: - exp = ParseListExpression(); + exp = CleanupExpression(ParseListExpression()); ConsumeToken(TK_SEMICOLON); } } @@ -3863,7 +4496,7 @@ Expression* Parser::ParseSwitchStatement(void) if (mScanner->mToken == TK_OPEN_PARENTHESIS) { mScanner->NextToken(); - sexp->mLeft = ParseRExpression(); + sexp->mLeft = CleanupExpression(ParseRExpression()); if (mScanner->mToken == TK_CLOSE_PARENTHESIS) mScanner->NextToken(); else diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 2e0c661..e889bce 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -46,6 +46,13 @@ protected: Expression* BuildMemberInitializer(Expression* vexp); void PrependMemberConstructor(Declaration* pthis, Declaration* cfunc); + void AddDefaultConstructors(Declaration* pthis); + + void ParseVariableInit(Declaration* ndec); + + Expression * AddFunctionCallRefReturned(Expression * exp); + Expression* CleanupExpression(Expression* exp); + Declaration* ParseBaseTypeDeclaration(uint64 flags); Declaration* ParseDeclaration(Declaration* pdec, bool variable, bool expression, Declaration * pthis = nullptr); Declaration* ParseStructDeclaration(uint64 flags, DecType dt); @@ -65,6 +72,8 @@ protected: Expression* ParseAssemblerAddOperand(Declaration* pcasm, int pcoffset); Expression* ParseAssemblerOperand(Declaration * pcasm, int pcoffset); + Expression* CheckOperatorOverload(Expression* exp); + void AddAssemblerRegister(const Ident* ident, int value); Declaration* ParseQualIdent(void); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 923167c..28905ef 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -1394,6 +1394,17 @@ void Scanner::NextRawToken(void) mToken = TK_USING; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "this")) mToken = TK_THIS; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator")) + { + NextRawToken(); + if (mToken == TK_ASSIGN) + { + mToken = TK_IDENT; + mTokenIdent = Ident::Unique("operator="); + } + else + mErrors->Error(mLocation, EERR_INVALID_OPERATOR, "Invalid operator token"); + } else { mToken = TK_IDENT;