From e37de95079333cb30f9cac6a912c69e8ef85207d Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Thu, 26 Dec 2024 14:57:23 +0100 Subject: [PATCH] Add bounded integer class --- include/opp/boundint.h | 45 +++++++++++++ oscar64/Constexpr.cpp | 3 + oscar64/Declaration.cpp | 109 +++++++++++++++++++++++++++++++- oscar64/Declaration.h | 3 + oscar64/Errors.cpp | 2 +- oscar64/NativeCodeGenerator.cpp | 26 ++++++++ oscar64/Parser.cpp | 34 +++++++++- oscar64/Scanner.cpp | 16 +++-- oscar64/Scanner.h | 3 +- 9 files changed, 231 insertions(+), 10 deletions(-) create mode 100644 include/opp/boundint.h diff --git a/include/opp/boundint.h b/include/opp/boundint.h new file mode 100644 index 0000000..d6076a5 --- /dev/null +++ b/include/opp/boundint.h @@ -0,0 +1,45 @@ +#ifndef OPP_BOUNDINT_H +#define OPP_BOUNDINT_H + +namespace opp { + + template + constexpr auto boundinttype(void) + { + if constexpr (tmin >= 0 && tmax <= 255) + return (char)0; + else if constexpr (tmin >= -128 && tmax <= 127) + return (signed char)0; + else + return (int)0; + } + + template + class boundint + { + protected: + decltype(boundinttype()) v; + public: + boundint(int i) + : v(i) + { + + } + + void operator=(int k) + { + __assume(k >= tmin && k <= tmax); + v = k; + } + + operator int() const + { + int k = v; + __assume(k >= tmin && k <= tmax); + return k; + } + }; + +} + +#endif diff --git a/oscar64/Constexpr.cpp b/oscar64/Constexpr.cpp index 93e2642..3431872 100644 --- a/oscar64/Constexpr.cpp +++ b/oscar64/Constexpr.cpp @@ -754,6 +754,9 @@ bool ConstexprInterpreter::AddParam(int& pos, Expression* pex, Declaration* dec) Expression* ConstexprInterpreter::EvalCall(Expression* exp) { + if (!exp->mLeft->mDecValue || !exp->mLeft->mDecValue->mValue) + return exp; + mProcType = exp->mLeft->mDecType; Expression* pex = exp->mRight; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 89b9ce8..bbbec84 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -491,6 +491,47 @@ Expression* Expression::LogicInvertExpression(void) } } +Expression* Expression::ToAlternateThis(Declaration* pthis, Declaration* nthis) +{ + Expression* left = mLeft ? mLeft->ToAlternateThis(pthis, nthis) : nullptr; + Expression* right = mRight ? mRight->ToAlternateThis(pthis, nthis) : nullptr; + Declaration* decType = mDecType, * decValue = mDecValue; + + if (decType == pthis->mBase) + decType = nthis->mBase; + else if (decType == pthis->mBase->mBase) + decType = nthis->mBase->mBase; + if (decValue == pthis) + decValue = nthis; + + if (mType == EX_QUALIFY && mLeft->mDecType != left->mDecType) + { + Declaration* pe = mLeft->mDecType->mParams, * ne = left->mDecType->mParams; + while (pe && ne && pe != mDecValue) + { + pe = pe->mNext; + ne = ne->mNext; + } + decValue = ne; + decType = ne->mBase; + } + + if (left == mLeft && right == mRight && decType == mDecType && decValue == mDecValue) + return this; + else + { + Expression* nexp = new Expression(mLocation, mType); + nexp->mLeft = left; + nexp->mRight = right; + nexp->mDecType = decType; + nexp->mDecValue = decValue; + nexp->mToken = mToken; + nexp->mConst = mConst; + + return nexp; + } +} + Expression* Expression::ConstantDereference(Errors* errors, LinkerSection* dataSection) { if (mType == EX_VARIABLE) @@ -1034,6 +1075,26 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio } } + else if (mType == EX_LOGICAL_AND && mLeft->mType == EX_CONSTANT) + { + if (mLeft->mDecValue->mType == DT_CONST_INTEGER) + { + if (mLeft->mDecValue->mInteger == 0) + return mLeft; + else + return mRight->ConstantFold(errors, dataSection); + } + } + else if (mType == EX_LOGICAL_OR && mLeft->mType == EX_CONSTANT) + { + if (mLeft->mDecValue->mType == DT_CONST_INTEGER) + { + if (mLeft->mDecValue->mInteger != 0) + return mLeft; + else + return mRight->ConstantFold(errors, dataSection); + } + } else if (mType == EX_CONDITIONAL && mLeft->mType == EX_CONSTANT) { if (mLeft->mDecValue->mType == DT_CONST_INTEGER) @@ -2058,6 +2119,7 @@ Declaration* Declaration::Clone(void) ndec->mMaxValue = mMaxValue; ndec->mCompilerOptions = mCompilerOptions; ndec->mParser = mParser; + ndec->mNumVars = mNumVars; return ndec; } @@ -2135,7 +2197,24 @@ Declaration* Declaration::ToStriped(int stripe) ndec->mParams = pnec; prev = pnec; p = p->mNext; - } + } + + Declaration* pndec = ndec->BuildPointer(mLocation); + + mScope->Iterate([=](const Ident* ident, Declaration* vdec) { + if (vdec->mType == DT_CONST_FUNCTION) + { + ndec->mScope->Insert(ident, vdec->ToAlternateThis(pndec)); + } + }); + + ndec->mDestructor = mDestructor ? mDestructor->ToAlternateThis(pndec) : nullptr; + ndec->mDefaultConstructor = mDefaultConstructor ? mDefaultConstructor->ToAlternateThis(pndec) : nullptr; + ndec->mCopyConstructor = mCopyConstructor ? mCopyConstructor->ToAlternateThis(pndec) : nullptr; + ndec->mMoveConstructor = mMoveConstructor ? mMoveConstructor->ToAlternateThis(pndec) : nullptr; + ndec->mVectorConstructor = mVectorConstructor ? mVectorConstructor->ToAlternateThis(pndec, 2) : nullptr; + ndec->mVectorDestructor = mVectorDestructor ? mVectorDestructor->ToAlternateThis(pndec, 2) : nullptr; + ndec->mVectorCopyConstructor = mVectorCopyConstructor ? mVectorCopyConstructor->ToAlternateThis(pndec, 2) : nullptr; } else if (mType == DT_TYPE_FUNCTION) { @@ -2244,6 +2323,34 @@ Declaration* Declaration::ToConstType(void) return mConst; } +Declaration* Declaration::ToAlternateThis(Declaration* pthis, int nthis) +{ + Declaration* ndec = this->Clone(); + + if (mType == DT_CONST_FUNCTION) + { + ndec->mBase = mBase->ToAlternateThis(pthis, nthis); + if (mValue) + ndec->mValue = mValue->ToAlternateThis(mBase->mParams, ndec->mBase->mParams); + } + else + { + Declaration* nparam = ndec->mParams->Clone(); + nparam->mBase = pthis; + if (nthis == 2) + { + Declaration* nparam2 = ndec->mParams->mNext->Clone(); + nparam2->mBase = pthis; + nparam->mNext = nparam2; + nparam2->mNext = ndec->mParams->mNext->mNext; + } + else + nparam->mNext = ndec->mParams->mNext; + ndec->mParams = nparam; + } + return ndec; +} + Declaration* Declaration::ToMutableType(void) { if (!(mFlags & DTF_CONST)) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 2a5a4a7..9a26024 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -264,6 +264,7 @@ public: Expression* ConstantDereference(Errors* errors, LinkerSection* dataSection); bool HasSideEffects(void) const; Expression* ListAppend(Expression* lexp); + Expression* ToAlternateThis(Declaration* pthis, Declaration* nthis); bool IsSame(const Expression* exp) const; bool IsRValue(void) const; @@ -271,6 +272,7 @@ public: bool IsConstRef(void) const; bool IsVolatile(void) const; + void Dump(int ident) const; }; @@ -335,6 +337,7 @@ public: Declaration* ToConstType(void); Declaration* ToMutableType(void); Declaration* ToVolatileType(void); + Declaration* ToAlternateThis(Declaration* pthis, int nthis = 1); Declaration* ToStriped(int stripe); Declaration* ToStriped(Errors* errors); diff --git a/oscar64/Errors.cpp b/oscar64/Errors.cpp index cf22249..25b6052 100644 --- a/oscar64/Errors.cpp +++ b/oscar64/Errors.cpp @@ -54,7 +54,7 @@ void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const char else fprintf(stderr, "oscar64: %s %d: %s '%s' != '%s'\n", level, eid, msg, info1, info2); } - + if (mErrorCount > 10 || eid >= EFATAL_GENERIC) exit(20); } diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index f8b1fb0..8cf2339 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -46583,6 +46583,32 @@ bool NativeCodeBasicBlock::PeepHoleOptimizerIterate4(int i, int pass) return true; } + else if ( + mIns[i + 0].mType == ASMIT_STA && + mIns[i + 1].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDX, mIns[i + 1].mMode) && + mIns[i + 2].mType == ASMIT_STA && HasAsmInstructionMode(ASMIT_STX, mIns[i + 2].mMode) && + mIns[i + 3].mType == ASMIT_LDX && mIns[i + 3].SameEffectiveAddress(mIns[i + 0])) + { + mIns[i + 0].mLive |= LIVE_CPU_REG_A; + mIns[i + 1].mType = ASMIT_LDX; mIns[i + 1].mLive |= LIVE_CPU_REG_X; + mIns[i + 2].mType = ASMIT_STX; mIns[i + 2].mLive |= LIVE_CPU_REG_A; + mIns[i + 3].mType = ASMIT_TAX; mIns[i + 3].mMode = ASMIM_IMPLIED; + + return true; + } + else if ( + mIns[i + 0].mType == ASMIT_STA && + mIns[i + 1].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDY, mIns[i + 1].mMode) && + mIns[i + 2].mType == ASMIT_STA && HasAsmInstructionMode(ASMIT_STY, mIns[i + 2].mMode) && + mIns[i + 3].mType == ASMIT_LDY && mIns[i + 3].SameEffectiveAddress(mIns[i + 0])) + { + mIns[i + 0].mLive |= LIVE_CPU_REG_A; + mIns[i + 1].mType = ASMIT_LDY; mIns[i + 1].mLive |= LIVE_CPU_REG_Y; + mIns[i + 2].mType = ASMIT_STY; mIns[i + 2].mLive |= LIVE_CPU_REG_A; + mIns[i + 3].mType = ASMIT_TAY; mIns[i + 3].mMode = ASMIM_IMPLIED; + + return true; + } else if ( mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_LDY && mIns[i + 1].mMode == ASMIM_IMMEDIATE && diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 906fc21..5e02f27 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -869,6 +869,14 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified, Decl mScanner->NextToken(); break; + case TK_DECLTYPE: + { + mScanner->NextToken(); + Expression* exp = ParseExpression(true); + dec = exp->mDecType; + } + break; + case TK_IDENT: pident = mScanner->mTokenIdent; mScanner->NextToken(); @@ -5321,7 +5329,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (pdec) { - if (!ndec->mBase->IsSame(pdec->mBase)) + if (!ndec->mBase->IsSame(pdec->mBase) && !(ndec->mBase->mBase->mType == DT_TYPE_AUTO && ndec->mBase->IsSameParams(pdec->mBase))) { ndec->mBase->IsSameParams(pdec->mBase); ndec->mBase->IsSame(pdec->mBase); @@ -6384,6 +6392,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs, bool tid) case TK_STATIC: case TK_AUTO: case TK_STRIPED: + case TK_DECLTYPE: exp = ParseDeclarationExpression(nullptr); break; @@ -7461,6 +7470,7 @@ Expression* Parser::CoerceExpression(Expression* exp, Declaration* type) nexp->mLeft->mDecType = fexp->mBase; nexp->mLeft->mDecValue = fexp; nexp->mRight = aexp; + nexp->mDecType = fexp->mBase->mBase; return nexp; } @@ -9349,6 +9359,9 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) Declaration* tdec = exp->mLeft->mDecType; while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) tdec = tdec->mBase; + Declaration* rtdec = exp->mRight->mDecType; + while (rtdec->mType == DT_TYPE_REFERENCE || rtdec->mType == DT_TYPE_RVALUEREF) + rtdec = rtdec->mBase; if (tdec->mType == DT_TYPE_STRUCT) { @@ -9383,6 +9396,18 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) exp = nexp; } } + + if (exp->mType != EX_CALL && !nexp2 && (tdec->mType == DT_TYPE_STRUCT || rtdec->mType == DT_TYPE_STRUCT)) + { + if ((exp->mLeft->mDecType->IsIntegerType() || CanCoerceExpression(exp->mLeft, TheSignedIntTypeDeclaration)) && + (exp->mRight->mDecType->IsIntegerType() || CanCoerceExpression(exp->mRight, TheSignedIntTypeDeclaration))) + { + exp->mLeft = CoerceExpression(exp->mLeft, TheSignedIntTypeDeclaration); + exp->mRight = CoerceExpression(exp->mRight, TheSignedIntTypeDeclaration); + if (exp->mType == EX_BINARY) + exp->mDecType = TheSignedIntTypeDeclaration; + } + } } } else if (exp->mType == EX_PREFIX) @@ -9781,6 +9806,12 @@ void Parser::SkipStatement(void) mScanner->NextToken(); } } + else if (ConsumeTokenIf(TK_IF)) + { + SkipStatement(); + if (ConsumeTokenIf(TK_ELSE)) + SkipStatement(); + } else { while (!ConsumeTokenIf(TK_SEMICOLON)) @@ -12540,6 +12571,7 @@ bool Parser::IsTypeToken(void) case TK_STATIC: case TK_AUTO: case TK_STRIPED: + case TK_DECLTYPE: return true; case TK_IDENT: { diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 4621b4d..e52a4b7 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -173,6 +173,7 @@ const char* TokenNames[] = "'friend'", "'constexpr'", "'typename'", + "'decltype'", }; @@ -355,7 +356,7 @@ Scanner::Scanner(Errors* errors, Preprocessor* preprocessor) mToken = TK_NONE; mUngetToken = TK_NONE; mReplay = nullptr; - mRecord = mRecordLast = nullptr; + mRecord = mRecordLast = mRecordPrev = nullptr; mOnceDict = new MacroDict(); @@ -372,13 +373,13 @@ Scanner::~Scanner(void) void Scanner::BeginRecord(void) { - mRecord = mRecordLast = new TokenSequence(this); + mRecord = mRecordLast = mRecordPrev = new TokenSequence(this); } TokenSequence* Scanner::CompleteRecord(void) { TokenSequence* seq = mRecord; - mRecord = mRecordLast = nullptr; + mRecord = mRecordLast = mRecordPrev = nullptr; return seq; } @@ -483,6 +484,8 @@ void Scanner::UngetToken(Token token) { mUngetToken = mToken; mToken = token; + if (mRecord) + mRecordLast = mRecordPrev; } void Scanner::NextToken(void) @@ -491,10 +494,8 @@ void Scanner::NextToken(void) { mToken = mUngetToken; mUngetToken = TK_NONE; - return; } - - if (mReplay) + else if (mReplay) { mLocation = mReplay->mLocation; mToken = mReplay->mToken; @@ -515,6 +516,7 @@ void Scanner::NextToken(void) if (mRecord) { + mRecordPrev = mRecordLast; mRecordLast->mNext = new TokenSequence(this); mRecordLast = mRecordLast->mNext; } @@ -1846,6 +1848,8 @@ void Scanner::NextRawToken(void) mToken = TK_CONSTEXPR; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "typename")) mToken = TK_TYPENAME; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "decltype")) + mToken = TK_DECLTYPE; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator")) { NextRawToken(); diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 96a3c1c..caaf9e7 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -172,6 +172,7 @@ enum Token TK_FRIEND, TK_CONSTEXPR, TK_TYPENAME, + TK_DECLTYPE, NUM_TOKENS }; @@ -315,7 +316,7 @@ protected: Token mUngetToken; const TokenSequence* mReplay; - TokenSequence* mRecord, * mRecordLast; + TokenSequence* mRecord, * mRecordLast, * mRecordPrev; void StringToken(char terminator, char mode); void CharToken(char mode);