diff --git a/README.md b/README.md index 7454ff7..5d18225 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ The goal was also to implement the C99 standard and not some subset for performa After extensive optimizations it turns out, that the interpreted code is not significantly smaller than the native code in most scenarios (although there are cases where the difference is significant). - + ## Limits and Errors There are still several open areas, but most targets have been reached. The current Dhrystone performance is 94 iterations per second with byte code (11696) and 395 iterations with native code (10425 Bytes). This clearly shows that Dhrystone is not a valid benchmark for optimizing compilers, because it puts the 6502 on par with a 4MHz 8088 or 68k, which it clearly is not. @@ -48,6 +48,18 @@ There are still several open areas, but most targets have been reached. The cur ### Native code generation +### C++ support level + +The compiler will most likely not support a current C++ standard in the near future, but several C++ features are already implemented. The compiler can be switched into C++ mode with the command line option -pp or by providing a source file with a .cpp extension. + +Supported Features: + +* namespaces +* reference types +* member functions +* constructors and destructors +* operator overloading (assignment) + ## Installation and Usage ### Installing on windows @@ -62,7 +74,7 @@ The compiler can also be built using MSVC or GCC. A visual studio project and a The compiler is command line driven, and creates an executable .prg file. - oscar64 {-i=includePath} [-o=output.prg] [-rt=runtime.c] [-tf=format] [-tm=machine] [-e] [-n] [-dSYMBOL[=value]] {source.c} + oscar64 {-i=includePath} [-o=output.prg] [-rt=runtime.c] [-tf=format] [-tm=machine] [-e] [-n] [-dSYMBOL[=value]] {source.c|source.cpp} * -v : verbose output for diagnostics * -v2 : more verbose output @@ -90,6 +102,7 @@ The compiler is command line driven, and creates an executable .prg file. * -fz : add a compressed binary file to the disk image * -xz : extended zero page usage, more zero page space, but no return to basic * -cid : cartridge type ID, used by vice emulator +* -pp : compile in C++ mode A list of source files can be provided. diff --git a/autotest/arrayconstruct.cpp b/autotest/arrayconstruct.cpp new file mode 100644 index 0000000..845a9bb --- /dev/null +++ b/autotest/arrayconstruct.cpp @@ -0,0 +1,151 @@ +#include + +int t, n, m, k; + +struct C1 +{ + int a; + + C1(void); + ~C1(void); + C1(const C1 & c); + C1 & operator=(const C1 & c); +}; + +struct C2 +{ + C1 nc[10], mc[20]; +}; + +C1::C1(void) +{ + a = 1; + n++; + t++; +} + +C1::C1(const C1 & c) +{ + a = c.a; + k++; + t++; +} + +C1 & C1::operator=(const C1 & c) +{ + a = c.a; + m++; + return *this; +} + +C1::~C1(void) +{ + t--; +} + +void test_local_init(void) +{ + n = 0; + + { + C1 c[10]; + } + + assert(n == 10 && t == 0); +} + +void test_member_init(void) +{ + n = 0; + + { + C2 d; + } + + assert(n == 30 && t == 0); +} + +void test_member_array_init(void) +{ + n = 0; + + { + C2 d[5]; + } + + assert(n == 150 && t == 0); +} + +void test_local_copy(void) +{ + n = 0; + k = 0; + + { + C1 c[10]; + C1 d(c[4]); + } + + assert(n == 10 && k == 1 && t == 0); +} + +void test_member_copy(void) +{ + n = 0; + k = 0; + + { + C2 d; + C2 e(d); + } + + assert(n == 30 && k == 30 && t == 0); +} + +void test_local_assign(void) +{ + n = 0; + k = 0; + m = 0; + + { + C1 c[10]; + C1 d[5]; + + d[4] = c[2]; + } + + assert(n == 15 && k == 0 && m == 1 && t == 0); +} + +void test_member_assign(void) +{ + n = 0; + k = 0; + m = 0; + + { + C2 d; + C2 e; + e = d; + } + + assert(n == 60 && k == 0 && m == 30 && t == 0); +} + + +int main(void) +{ + test_local_init(); + test_member_init(); + test_member_array_init(); + + test_local_copy(); + test_member_copy(); + + test_local_assign(); + test_member_assign(); + + return 0; +} + diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 26e10c4..4ec42d3 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -9,6 +9,9 @@ rem @echo off @call :test copyassign.cpp @if %errorlevel% neq 0 goto :error +@call :test arrayconstruct.cpp +@if %errorlevel% neq 0 goto :error + @call :test stdlibtest.c @if %errorlevel% neq 0 goto :error diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index aa04d09..8f180ec 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -778,7 +778,8 @@ 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), mPrev(nullptr), mConst(nullptr), - mConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), + mConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), + mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(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) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 6f49477..cf2b6b1 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -222,7 +222,10 @@ public: Location mLocation, mEndLocation; DecType mType; Token mToken; - Declaration* mBase, *mParams, * mNext, * mPrev, * mConst, * mConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment; + Declaration * mBase, * mParams, * mNext, * mPrev, * mConst; + Declaration * mConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment; + Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment; + Expression* mValue; DeclarationScope* mScope; int mOffset, mSize, mVarIndex, mNumVars, mComplexity, mLocalSize, mAlignment, mFastCallBase, mFastCallSize, mStride, mStripe; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 9517e7d..a8e199d 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, "test_retparam_value"); + CheckFunc = !strcmp(mIdent->mString, "test"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 13bd34f..2017ad3 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -4329,6 +4329,13 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod if (proc->mIdent && !strcmp(proc->mIdent->mString, "test_retparam_value")) exp->Dump(0); #endif +#if 0 + if (proc->mIdent) + { + printf("TRANS %s\n", proc->mIdent->mString); + exp->Dump(0); + } +#endif uint64 outerCompilerOptions = mCompilerOptions; mCompilerOptions = dec->mCompilerOptions; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 2226e4e..7d1d0fd 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -36463,6 +36463,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass 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) { + mIns[i + 1].mLive |= LIVE_CPU_REG_A; mIns[i + 2].mType = ASMIT_ORA; mIns[i + 2].mLive |= mIns[i + 3].mLive & LIVE_CPU_REG_Z; mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 94863ce..c05812d 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -1243,43 +1243,79 @@ void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) sexp->mRight = cfunc->mValue; cfunc->mValue = sexp; } - else if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mConstructor) + else { - Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); - qexp->mLeft = thisexp; - qexp->mDecValue = dec; - qexp->mDecType = dec->mBase; + Declaration* bdec = dec->mBase; + while (bdec->mType == DT_TYPE_ARRAY) + bdec = bdec->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; - - 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 (bdec->mType == DT_TYPE_STRUCT && bdec->mConstructor) { - cexp->mDecValue = mdec; - cexp->mDecType = cexp->mDecValue->mBase; + Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); + qexp->mLeft = thisexp; + qexp->mDecValue = dec; + + Expression* dexp; + + if (dec->mSize == bdec->mSize) + { + qexp->mDecType = bdec; + + 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 = bdec; + pexp->mDecType->mSize = 2; + + Declaration* mdec = bdec->mConstructor; + while (mdec && mdec->mBase->mParams->mNext) + mdec = mdec->mNext; + + 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"); + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; + } + else + { + qexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + qexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + qexp->mDecType->mBase = bdec; + qexp->mDecType->mSize = 2; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mVectorConstructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + ncdec->mBase = TheUnsignedIntTypeDeclaration; + ncdec->mInteger = dec->mSize / bdec->mSize; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + dexp->mRight->mLeft = qexp; + dexp->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); + dexp->mRight->mRight->mDecType = ncdec->mBase; + dexp->mRight->mRight->mDecValue = ncdec; + } + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + + sexp->mLeft = dexp; + sexp->mRight = cfunc->mValue; + cfunc->mValue = sexp; } - 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; } } @@ -1352,12 +1388,21 @@ void Parser::AddDefaultConstructors(Declaration* pthis) Declaration* dec = pthis->mBase->mParams; while (dec) { - if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT) + if (dec->mType == DT_ELEMENT) { - if (dec->mBase->mDestructor) - simpleDestructor = false; - if (dec->mBase->mCopyAssignment) - simpleAssignment = false; + Declaration* bdec = dec->mBase; + int nitems = 1; + + while (bdec->mType == DT_TYPE_ARRAY) + bdec = bdec->mBase; + + if (bdec->mType == DT_TYPE_STRUCT) + { + if (bdec->mDestructor) + simpleDestructor = false; + if (bdec->mCopyAssignment) + simpleAssignment = false; + } } dec = dec->mNext; } @@ -1521,27 +1566,65 @@ void Parser::AddDefaultConstructors(Declaration* pthis) Expression* mexp; - if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mCopyConstructor) + Declaration* bdec = dec->mBase; + while (bdec->mType == DT_TYPE_ARRAY) + bdec = bdec->mBase; + + if (bdec->mType == DT_TYPE_STRUCT && bdec->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; + if (dec->mSize == bdec->mSize) + { + 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; + Declaration* mdec = dec->mBase->mCopyConstructor; - Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); - cexp->mDecValue = mdec; - cexp->mDecType = cexp->mDecValue->mBase; + 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; + 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 + { + lexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + lexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + lexp->mDecType->mBase = bdec; + lexp->mDecType->mSize = 2; + + rexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + rexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + rexp->mDecType->mBase = bdec; + rexp->mDecType->mSize = 2; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mVectorCopyConstructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + ncdec->mBase = TheUnsignedIntTypeDeclaration; + ncdec->mInteger = dec->mSize / bdec->mSize; + + mexp = new Expression(mScanner->mLocation, EX_CALL); + mexp->mLeft = cexp; + mexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + mexp->mRight->mLeft = lexp; + mexp->mRight->mRight = new Expression(mScanner->mLocation, EX_LIST); + mexp->mRight->mRight->mLeft = rexp; + mexp->mRight->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); + mexp->mRight->mRight->mRight->mDecType = ncdec->mBase; + mexp->mRight->mRight->mRight->mDecValue = ncdec; + + } } else { @@ -1661,27 +1744,64 @@ void Parser::AddDefaultConstructors(Declaration* pthis) Expression* mexp; - if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mCopyAssignment) + Declaration* bdec = dec->mBase; + while (bdec->mType == DT_TYPE_ARRAY) + bdec = bdec->mBase; + + if (bdec->mType == DT_TYPE_STRUCT && bdec->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; + if (dec->mSize == bdec->mSize) + { + 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; + Declaration* mdec = bdec->mCopyAssignment; - Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); - cexp->mDecValue = mdec; - cexp->mDecType = cexp->mDecValue->mBase; + 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; + 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 + { + lexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + lexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + lexp->mDecType->mBase = bdec; + lexp->mDecType->mSize = 2; + + rexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + rexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + rexp->mDecType->mBase = bdec; + rexp->mDecType->mSize = 2; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mVectorCopyAssignment; + cexp->mDecType = cexp->mDecValue->mBase; + + Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + ncdec->mBase = TheUnsignedIntTypeDeclaration; + ncdec->mInteger = dec->mSize / bdec->mSize; + + mexp = new Expression(mScanner->mLocation, EX_CALL); + mexp->mLeft = cexp; + mexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + mexp->mRight->mLeft = lexp; + mexp->mRight->mRight = new Expression(mScanner->mLocation, EX_LIST); + mexp->mRight->mRight->mLeft = rexp; + mexp->mRight->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); + mexp->mRight->mRight->mRight->mDecType = ncdec->mBase; + mexp->mRight->mRight->mRight->mDecValue = ncdec; + } } else { @@ -1707,6 +1827,373 @@ void Parser::AddDefaultConstructors(Declaration* pthis) } } + + Declaration* dcons = pthis->mBase->mConstructor; + while (dcons && dcons->mBase->mParams->mNext) + dcons = dcons->mNext; + + if (dcons && !pthis->mBase->mVectorConstructor) + { + Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); + ctdec->mSize = 0; + Declaration* pdec = nullptr; + ctdec->mBase = TheVoidTypeDeclaration; + ctdec->mFlags |= DTF_DEFINED; + + Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + adec->mVarIndex = 0; + adec->mOffset = 0; + adec->mBase = TheUnsignedIntTypeDeclaration; + adec->mSize = adec->mBase->mSize; + adec->mIdent = adec->mQualIdent = Ident::Unique("n"); + + ctdec->mParams = adec; + + Declaration* vthis = pthis->Clone(); + vthis->mFlags &= ~DTF_CONST; + PrependThisArgument(ctdec, vthis); + + 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->mVectorConstructor = 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; + + Expression* pexp = new Expression(mScanner->mLocation, EX_VARIABLE); + pexp->mDecType = vthis; + pexp->mDecValue = ctdec->mParams; + + Expression* aexp = new Expression(mScanner->mLocation, EX_VARIABLE); + aexp->mDecType = TheUnsignedIntTypeDeclaration; + aexp->mDecValue = adec; + + Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + iexp->mToken = TK_INC; + iexp->mLeft = pexp; + + Expression* dexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + dexp->mToken = TK_DEC; + dexp->mLeft = aexp; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT); + fexp->mDecValue = dcons; + fexp->mDecType = fexp->mDecValue->mBase; + + Expression*cexp = new Expression(mScanner->mLocation, EX_CALL); + cexp->mLeft = fexp; + cexp->mRight = iexp; + + Expression * wexp = new Expression(mScanner->mLocation, EX_WHILE); + wexp->mLeft = aexp; + wexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); + wexp->mRight->mLeft = cexp; + wexp->mRight->mRight = dexp; + + cdec->mValue = wexp; + } + + if (pthis->mBase->mDestructor && !pthis->mBase->mVectorDestructor) + { + Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); + ctdec->mSize = 0; + Declaration* pdec = nullptr; + ctdec->mBase = TheVoidTypeDeclaration; + ctdec->mFlags |= DTF_DEFINED; + + Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + adec->mVarIndex = 0; + adec->mOffset = 0; + adec->mBase = TheUnsignedIntTypeDeclaration; + adec->mSize = adec->mBase->mSize; + adec->mIdent = adec->mQualIdent = Ident::Unique("n"); + + ctdec->mParams = adec; + + Declaration* vthis = pthis->Clone(); + vthis->mFlags &= ~DTF_CONST; + PrependThisArgument(ctdec, vthis); + + 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->mVectorDestructor = cdec; + + char dname[100]; + strcpy_s(dname, "~"); + strcat_s(dname, pthis->mBase->mIdent->mString); + cdec->mIdent = Ident::Unique(dname); + 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; + + Expression* pexp = new Expression(mScanner->mLocation, EX_VARIABLE); + pexp->mDecType = vthis; + pexp->mDecValue = ctdec->mParams; + + Expression* aexp = new Expression(mScanner->mLocation, EX_VARIABLE); + aexp->mDecType = TheUnsignedIntTypeDeclaration; + aexp->mDecValue = adec; + + Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + iexp->mToken = TK_INC; + iexp->mLeft = pexp; + + Expression* dexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + dexp->mToken = TK_DEC; + dexp->mLeft = aexp; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT); + fexp->mDecValue = pthis->mBase->mDestructor; + fexp->mDecType = fexp->mDecValue->mBase; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CALL); + cexp->mLeft = fexp; + cexp->mRight = iexp; + + Expression* wexp = new Expression(mScanner->mLocation, EX_WHILE); + wexp->mLeft = aexp; + wexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); + wexp->mRight->mLeft = cexp; + wexp->mRight->mRight = dexp; + + cdec->mValue = wexp; + } + + if (pthis->mBase->mCopyConstructor && !pthis->mBase->mVectorCopyConstructor) + { + Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); + ctdec->mSize = 0; + Declaration* pdec = nullptr; + ctdec->mBase = TheVoidTypeDeclaration; + ctdec->mFlags |= DTF_DEFINED; + + Declaration* sdec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + sdec->mVarIndex = 0; + sdec->mOffset = 0; + sdec->mBase = pthis->Clone(); + sdec->mBase->mFlags &= ~DTF_CONST; + sdec->mSize = sdec->mBase->mSize; + sdec->mIdent = sdec->mQualIdent = Ident::Unique("_"); + + Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + adec->mVarIndex = 2; + adec->mOffset = 0; + adec->mBase = TheUnsignedIntTypeDeclaration; + adec->mSize = adec->mBase->mSize; + adec->mIdent = adec->mQualIdent = Ident::Unique("n"); + + sdec->mNext = adec; + ctdec->mParams = sdec; + + Declaration* vthis = pthis->Clone(); + vthis->mFlags &= ~DTF_CONST; + PrependThisArgument(ctdec, vthis); + + 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->mVectorCopyConstructor = 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; + + Expression* pexp = new Expression(mScanner->mLocation, EX_VARIABLE); + pexp->mDecType = vthis; + pexp->mDecValue = ctdec->mParams; + + Expression* psexp = new Expression(mScanner->mLocation, EX_VARIABLE); + psexp->mDecType = vthis; + psexp->mDecValue = sdec; + + Expression* aexp = new Expression(mScanner->mLocation, EX_VARIABLE); + aexp->mDecType = TheUnsignedIntTypeDeclaration; + aexp->mDecValue = adec; + + Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + iexp->mToken = TK_INC; + iexp->mLeft = pexp; + + Expression* isexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + isexp->mToken = TK_INC; + isexp->mLeft = psexp; + + Expression* disexp = new Expression(mScanner->mLocation, EX_PREFIX); + disexp->mToken = TK_MUL; + disexp->mLeft = isexp; + disexp->mDecType = vthis->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + dexp->mToken = TK_DEC; + dexp->mLeft = aexp; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT); + fexp->mDecValue = pthis->mBase->mCopyConstructor; + fexp->mDecType = fexp->mDecValue->mBase; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CALL); + cexp->mLeft = fexp; + cexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + cexp->mRight->mLeft = iexp; + cexp->mRight->mRight = disexp; + + Expression* wexp = new Expression(mScanner->mLocation, EX_WHILE); + wexp->mLeft = aexp; + wexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); + wexp->mRight->mLeft = cexp; + wexp->mRight->mRight = dexp; + + cdec->mValue = wexp; + } + + if (pthis->mBase->mCopyAssignment && !pthis->mBase->mVectorCopyAssignment) + { + Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); + ctdec->mSize = 0; + Declaration* pdec = nullptr; + ctdec->mBase = TheVoidTypeDeclaration; + ctdec->mFlags |= DTF_DEFINED; + + Declaration* sdec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + sdec->mVarIndex = 0; + sdec->mOffset = 0; + sdec->mBase = pthis->Clone(); + sdec->mBase->mFlags &= ~DTF_CONST; + sdec->mSize = sdec->mBase->mSize; + sdec->mIdent = sdec->mQualIdent = Ident::Unique("_"); + + Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + adec->mVarIndex = 2; + adec->mOffset = 0; + adec->mBase = TheUnsignedIntTypeDeclaration; + adec->mSize = adec->mBase->mSize; + adec->mIdent = adec->mQualIdent = Ident::Unique("n"); + + sdec->mNext = adec; + ctdec->mParams = sdec; + + Declaration* vthis = pthis->Clone(); + vthis->mFlags &= ~DTF_CONST; + PrependThisArgument(ctdec, vthis); + + 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->mVectorCopyAssignment = 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; + + Expression* pexp = new Expression(mScanner->mLocation, EX_VARIABLE); + pexp->mDecType = vthis; + pexp->mDecValue = ctdec->mParams; + + Expression* psexp = new Expression(mScanner->mLocation, EX_VARIABLE); + psexp->mDecType = vthis; + psexp->mDecValue = sdec; + + Expression* aexp = new Expression(mScanner->mLocation, EX_VARIABLE); + aexp->mDecType = TheUnsignedIntTypeDeclaration; + aexp->mDecValue = adec; + + Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + iexp->mToken = TK_INC; + iexp->mLeft = pexp; + + Expression* isexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + isexp->mToken = TK_INC; + isexp->mLeft = psexp; + + Expression* disexp = new Expression(mScanner->mLocation, EX_PREFIX); + disexp->mToken = TK_MUL; + disexp->mLeft = isexp; + disexp->mDecType = vthis->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + dexp->mToken = TK_DEC; + dexp->mLeft = aexp; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT); + fexp->mDecValue = pthis->mBase->mCopyAssignment; + fexp->mDecType = fexp->mDecValue->mBase; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CALL); + cexp->mLeft = fexp; + cexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + cexp->mRight->mLeft = iexp; + cexp->mRight->mRight = disexp; + + Expression* wexp = new Expression(mScanner->mLocation, EX_WHILE); + wexp->mLeft = aexp; + wexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); + wexp->mRight->mLeft = cexp; + wexp->mRight->mRight = dexp; + + cdec->mValue = wexp; + } } void Parser::AppendMemberDestructor(Declaration* pthis) @@ -1730,35 +2217,71 @@ void Parser::AppendMemberDestructor(Declaration* pthis) dec = dec->Last(); while (dec) { - if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mDestructor) + if (dec->mType == DT_ELEMENT) { - Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); - qexp->mLeft = thisexp; - qexp->mDecValue = dec; - qexp->mDecType = dec->mBase; + Declaration* bdec = dec->mBase; + while (bdec->mType == DT_TYPE_ARRAY) + bdec = bdec->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; + if (bdec->mType == DT_TYPE_STRUCT && bdec->mConstructor) + { + Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); + qexp->mLeft = thisexp; + qexp->mDecValue = dec; - Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); - cexp->mDecValue = dec->mBase->mDestructor; - cexp->mDecType = cexp->mDecValue->mBase; + Expression* dexp; - Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = pexp; + if (dec->mSize == bdec->mSize) + { + qexp->mDecType = bdec; - Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + 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 = bdec; + pexp->mDecType->mSize = 2; - sexp->mLeft = pthis->mBase->mDestructor->mValue; - sexp->mRight = dexp; + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; - pthis->mBase->mDestructor->mValue = sexp; + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; + } + else + { + qexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + qexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + qexp->mDecType->mBase = bdec; + qexp->mDecType->mSize = 2; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mVectorDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + ncdec->mBase = TheUnsignedIntTypeDeclaration; + ncdec->mInteger = dec->mSize / bdec->mSize; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + dexp->mRight->mLeft = qexp; + dexp->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); + dexp->mRight->mRight->mDecType = ncdec->mBase; + dexp->mRight->mRight->mDecValue = ncdec; + } + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + + sexp->mLeft = pthis->mBase->mDestructor->mValue; + sexp->mRight = dexp; + + pthis->mBase->mDestructor->mValue = sexp; + } } dec = dec->mPrev; @@ -2615,62 +3138,116 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex { ParseVariableInit(ndec); } - else if ((mCompilerOptions & COPT_CPLUSPLUS) && ndec->mBase->mConstructor && ndec->mType == DT_VARIABLE && !pthis) + else if ((mCompilerOptions & COPT_CPLUSPLUS) && ndec->mType == DT_VARIABLE && !pthis) { // Find default constructor - Declaration* cdec = ndec->mBase->mConstructor; - while (cdec && cdec->mBase->mParams->mNext) - cdec = cdec->mNext; + Declaration* bdec = ndec->mBase; + while (bdec && bdec->mType == DT_TYPE_ARRAY) + bdec = bdec->mBase; - if (cdec) + if (bdec && bdec->mConstructor) { - Expression* vexp = new Expression(ndec->mLocation, EX_VARIABLE); - vexp->mDecType = ndec->mBase; - vexp->mDecValue = ndec; + Declaration* cdec = bdec->mConstructor; + while (cdec && cdec->mBase->mParams->mNext) + cdec = cdec->mNext; - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = cdec; - cexp->mDecType = cexp->mDecValue->mBase; - - Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); - fexp->mLeft = cexp; - - 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; - - fexp->mRight = texp; - - Expression* dexp = nullptr; - if (ndec->mBase->mDestructor) + if (cdec) { - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = ndec->mBase->mDestructor; - cexp->mDecType = cexp->mDecValue->mBase; + Expression* vexp = new Expression(ndec->mLocation, EX_VARIABLE); + vexp->mDecType = ndec->mBase; + vexp->mDecValue = ndec; - dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = texp; + 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_DEFINED; + texp->mDecType->mBase = bdec; + texp->mDecType->mSize = 2; + + if (bdec->mSize == ndec->mBase->mSize) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = cdec; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); + fexp->mLeft = cexp; + fexp->mRight = texp; + + 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 + { + Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + ncdec->mBase = TheUnsignedIntTypeDeclaration; + ncdec->mInteger = ndec->mSize / bdec->mSize; + + Expression * ncexp = new Expression(mScanner->mLocation, EX_CONSTANT); + ncexp->mDecType = ncdec->mBase; + ncexp->mDecValue = ncdec; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mVectorConstructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); + fexp->mLeft = cexp; + fexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + fexp->mRight->mLeft = vexp; + fexp->mRight->mRight = ncexp; + + Expression* dexp = nullptr; + if (bdec->mDestructor) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mVectorDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + dexp->mRight->mLeft = vexp; + dexp->mRight->mRight = ncexp; + } + + 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; + } } - - 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 + mErrors->Error(ndec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor for class", ndec->mBase->mIdent); } - else - mErrors->Error(ndec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor for class", ndec->mBase->mIdent); } if (storageFlags & DTF_EXPORT)