From b008d39eae869b8d72f7efcf50eb5761bc62fe46 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 18 Jun 2023 20:27:20 +0200 Subject: [PATCH] Function overloading in cpp mode --- oscar64/Declaration.cpp | 24 +++- oscar64/Declaration.h | 3 +- oscar64/Errors.h | 2 + oscar64/NativeCodeGenerator.cpp | 10 ++ oscar64/Parser.cpp | 231 +++++++++++++++++++++++++++----- oscar64/Parser.h | 5 +- 6 files changed, 236 insertions(+), 39 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index ba35f6f..ff2dce2 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -85,8 +85,11 @@ Declaration * DeclarationScope::Insert(const Ident* ident, Declaration* dec) return nullptr; } -Declaration* DeclarationScope::Lookup(const Ident* ident) +Declaration* DeclarationScope::Lookup(const Ident* ident, ScopeLevel limit) { + if (mLevel < limit) + return nullptr; + if (mHashSize > 0) { int hm = mHashSize - 1; @@ -900,6 +903,25 @@ bool Declaration::IsConstSame(const Declaration* dec) const return false; } +bool Declaration::IsSameParams(const Declaration* dec) const +{ + if (mType == DT_TYPE_FUNCTION && dec->mType == DT_TYPE_FUNCTION) + { + Declaration* ld = mParams, * rd = dec->mParams; + while (ld && rd) + { + if (!ld->mBase->IsSame(rd->mBase)) + return false; + ld = ld->mNext; + rd = rd->mNext; + } + + return !ld && !rd; + } + else + return false; +} + bool Declaration::IsSame(const Declaration* dec) const { if (this == dec) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 51707af..47d0c64 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -119,7 +119,7 @@ public: const Ident* Mangle(const Ident* ident) const; Declaration* Insert(const Ident* ident, Declaration* dec); - Declaration* Lookup(const Ident* ident); + Declaration* Lookup(const Ident* ident, ScopeLevel limit = SLEVEL_GLOBAL); void End(const Location & loc); @@ -234,6 +234,7 @@ public: bool IsSubType(const Declaration* dec) const; bool IsConstSame(const Declaration* dec) const; bool IsSameValue(const Declaration* dec) const; + bool IsSameParams(const Declaration* dec) const; bool IsIntegerType(void) const; bool IsNumericType(void) const; diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 3285f68..135d2b2 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -73,6 +73,8 @@ enum ErrorID ERRO_NOT_A_NAMESPACE, ERRO_NOT_A_BASE_CLASS, ERRO_THIS_OUTSIDE_OF_METHOD, + ERRO_NO_MATCHING_FUNCTION_CALL, + ERRO_AMBIGUOUS_FUNCTION_CALL, ERRR_STACK_OVERFLOW, ERRR_INVALID_NUMBER, diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 1999929..7d1ba92 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -18841,6 +18841,8 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool if (mEntryRequiredRegs[CPU_REG_A]) { mIns.Insert(0, NativeCodeInstruction(mIns[0].mIns, ASMIT_TAX)); + for (int i = 1; i < 8; i++) + mIns[i].mLive |= LIVE_CPU_REG_X; mIns.Insert(8, NativeCodeInstruction(mIns[0].mIns, ASMIT_TXA)); } @@ -31389,6 +31391,7 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) block->mIns.Insert(j, NativeCodeInstruction(ins.mIns, ASMIT_DEY)); yoffset--; } + while (yoffset < 0) { j++; @@ -31397,7 +31400,10 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) } if (j + 1 == block->mIns.Size() && (ins.mLive & LIVE_CPU_REG_Z) && ins.ChangesAccuAndFlag()) + { + ins.mLive |= LIVE_CPU_REG_A; block->mIns.Push(NativeCodeInstruction(ins.mIns, ASMIT_ORA, ASMIM_IMMEDIATE, 0)); + } } if (xoffset && xreg >= 0 && !(ins.mLive & LIVE_CPU_REG_X)) @@ -31408,6 +31414,7 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) block->mIns.Insert(j, NativeCodeInstruction(ins.mIns, ASMIT_DEX)); xoffset--; } + while (xoffset < 0) { j++; @@ -31416,7 +31423,10 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) } if (j + 1 == block->mIns.Size() && (ins.mLive & LIVE_CPU_REG_Z) && ins.ChangesAccuAndFlag()) + { + ins.mLive |= LIVE_CPU_REG_A; block->mIns.Push(NativeCodeInstruction(ins.mIns, ASMIT_ORA, ASMIM_IMMEDIATE, 0)); + } } if (yreg >= 0) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 9e85b09..a838821 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -86,18 +86,21 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) if (mScanner->mToken == TK_OPEN_BRACE) { - Declaration* othis = mThisPointer; - - mThisPointer = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); - mThisPointer->mFlags |= DTF_CONST | DTF_DEFINED; - mThisPointer->mBase = dec; - mThisPointer->mSize = 2; + Declaration* pthis = nullptr; + + if (mCompilerOptions & COPT_CPLUSPLUS) + { + pthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + pthis->mFlags |= DTF_CONST | DTF_DEFINED; + pthis->mBase = dec; + pthis->mSize = 2; + } mScanner->NextToken(); Declaration* mlast = nullptr; for (;;) { - Declaration* mdec = ParseDeclaration(nullptr, false, false); + Declaration* mdec = ParseDeclaration(nullptr, false, false, pthis); mdec->mQualIdent = dec->mScope->Mangle(mdec->mIdent); @@ -115,10 +118,29 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) if (mCompilerOptions & COPT_NATIVE) mdec->mFlags |= DTF_NATIVE; - if (dec->mScope->Insert(mdec->mIdent, mdec)) - mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); + Declaration* pdec = dec->mScope->Insert(mdec->mIdent, mdec); - if (mCompilationUnits->mScope->Insert(mdec->mQualIdent, mdec)) + if (pdec) + { + if (pdec->mType == DT_CONST_FUNCTION) + { + Declaration* pcdec = nullptr; + + while (pdec && !mdec->mBase->IsSameParams(pdec->mBase)) + { + pcdec = pdec; + pdec = pdec->mNext; + } + + if (!pdec) + pcdec->mNext = mdec; + else + mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); + } + else + mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); + } + else if (mCompilationUnits->mScope->Insert(mdec->mQualIdent, mdec)) mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); if (!(mdec->mFlags & DTF_DEFINED)) @@ -177,8 +199,6 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) dec->mParams = nullptr; dec->mFlags |= DTF_DEFINED; - - mThisPointer = othis; } return dec; @@ -1104,7 +1124,7 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) return exp; } -Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool expression) +Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool expression, Declaration* pthis) { bool definingType = false; uint64 storageFlags = 0, typeFlags = 0; @@ -1266,13 +1286,13 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } else { - if (ndec->mBase->mType == DT_TYPE_FUNCTION && mThisPointer) + if (ndec->mBase->mType == DT_TYPE_FUNCTION && pthis) { Declaration* adec = new Declaration(ndec->mLocation, DT_ARGUMENT); adec->mVarIndex = 0; adec->mOffset = 0; - adec->mBase = mThisPointer; + adec->mBase = pthis; adec->mSize = adec->mBase->mSize; adec->mNext = ndec->mBase->mParams; adec->mIdent = adec->mQualIdent = Ident::Unique("this"); @@ -1348,29 +1368,46 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex ndec->mBase->mFlags |= DTF_FUNC_THIS; } - if (!ndec->mBase->IsSame(pdec->mBase)) - mErrors->Error(ndec->mLocation, EERR_DECLARATION_DIFFERS, "Function declaration differs", ndec->mIdent); - else if (ndec->mFlags & ~pdec->mFlags & (DTF_HWINTERRUPT | DTF_INTERRUPT | DTF_FASTCALL | DTF_NATIVE)) - mErrors->Error(ndec->mLocation, EERR_DECLARATION_DIFFERS, "Function call type declaration differs", ndec->mIdent); - else + if (mCompilerOptions & COPT_CPLUSPLUS) { - // - // Take parameter names from new declaration - // - Declaration* npdec = ndec->mBase->mParams, *ppdec = pdec->mBase->mParams; - while (npdec && ppdec) + Declaration* pcdec = nullptr; + + while (pdec && !ndec->mBase->IsSameParams(pdec->mBase)) { - if (npdec->mIdent) - { - ppdec->mIdent = npdec->mIdent; - ppdec->mQualIdent = npdec->mQualIdent; - } - npdec = npdec->mNext; - ppdec = ppdec->mNext; + pcdec = pdec; + pdec = pdec->mNext; } + + if (!pdec) + pcdec->mNext = ndec; } - ndec = pdec; + if (pdec) + { + if (!ndec->mBase->IsSame(pdec->mBase)) + mErrors->Error(ndec->mLocation, EERR_DECLARATION_DIFFERS, "Function declaration differs", ndec->mIdent); + else if (ndec->mFlags & ~pdec->mFlags & (DTF_HWINTERRUPT | DTF_INTERRUPT | DTF_FASTCALL | DTF_NATIVE)) + mErrors->Error(ndec->mLocation, EERR_DECLARATION_DIFFERS, "Function call type declaration differs", ndec->mIdent); + else + { + // + // Take parameter names from new declaration + // + Declaration* npdec = ndec->mBase->mParams, * ppdec = pdec->mBase->mParams; + while (npdec && ppdec) + { + if (npdec->mIdent) + { + ppdec->mIdent = npdec->mIdent; + ppdec->mQualIdent = npdec->mQualIdent; + } + npdec = npdec->mNext; + ppdec = ppdec->mNext; + } + } + + ndec = pdec; + } } else if (ndec->mFlags & DTF_EXTERN) { @@ -1772,7 +1809,7 @@ Expression* Parser::ParseSimpleExpression(void) mScanner->NextToken(); break; case TK_IDENT: - if (mThisPointer) + if (mThisPointer && !mScope->Lookup(mScanner->mTokenIdent, SLEVEL_FUNCTION)) { dec = mThisPointer->mBase->mBase->mScope->Lookup(mScanner->mTokenIdent); if (dec) @@ -1969,10 +2006,14 @@ Expression* Parser::ParseQualify(Expression* exp) Expression* texp = new Expression(nexp->mLocation, EX_PREFIX); texp->mToken = TK_BINARY_AND; texp->mLeft = exp; + 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; if (nexp->mRight) { - Expression* lexp = new Expression(nexp->mLocation, EX_SEQUENCE); + Expression* lexp = new Expression(nexp->mLocation, EX_LIST); lexp->mLeft = texp; lexp->mRight = nexp->mRight; nexp->mRight = lexp; @@ -1980,6 +2021,9 @@ Expression* Parser::ParseQualify(Expression* exp) else nexp->mRight = texp; + ResolveOverloadCall(nexp->mLeft, nexp->mRight); + nexp->mDecType = nexp->mLeft->mDecType->mBase; + exp = nexp; } } @@ -1999,6 +2043,116 @@ Expression* Parser::ParseQualify(Expression* exp) return exp; } +int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) +{ + Declaration* pdec = fdec->mParams; + + int dist = 0; + + while (pexp) + { + Expression* ex = pexp; + if (pexp->mType == EX_LIST) + { + ex = pexp->mLeft; + pexp = pexp->mRight; + } + else + pexp = nullptr; + + if (pdec) + { + Declaration* ptype = pdec->mBase; + Declaration* etype = ex->mDecType; + if (etype->mType == DT_TYPE_REFERENCE) + etype = etype->mBase; + + if (ptype->mType == DT_TYPE_INTEGER && etype->mType == DT_TYPE_INTEGER) + ; + else if (ptype->mType == DT_TYPE_FLOAT && etype->mType == DT_TYPE_FLOAT) + ; + else if (ptype->mType == DT_TYPE_INTEGER && etype->mType == DT_TYPE_FLOAT) + dist += 8; + else if (ptype->mType == DT_TYPE_FLOAT && etype->mType == DT_TYPE_INTEGER) + dist++; + else if (ptype->IsSame(ex->mDecType)) + ; + else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->mType == DT_TYPE_STRUCT && etype->mType == DT_TYPE_STRUCT) + { + int ncast = 0; + Declaration* ext = ex->mDecType; + while (ext && !ext->IsConstSame(ptype->mBase)) + ext = ext->mBase; + + if (ext) + { + if ((etype->mFlags & DTF_CONST) && !(ptype->mBase->mFlags & DTF_CONST)) + return INT_MAX; + + dist += 16 * ncast; + } + else + return INT_MAX; + } + else if (ptype->IsSubType(ex->mDecType)) + dist += 256; + else + return INT_MAX; + + pdec = pdec->mNext; + } + else if (fdec->mFlags & DTF_VARIADIC) + { + dist += 1024; + break; + } + else + return INT_MAX; + } + + if (pdec) + return INT_MAX; + + return dist; +} + +void Parser::ResolveOverloadCall(Expression* cexp, Expression* pexp) +{ + if (cexp->mDecValue) + { + Declaration* fdec = cexp->mDecValue; + if (fdec->mType == DT_CONST_FUNCTION && fdec->mNext) + { + Declaration* dbest = nullptr; + int ibest = INT_MAX, nbest = 0; + + while (fdec) + { + int d = OverloadDistance(fdec->mBase, pexp); + if (d < ibest) + { + dbest = fdec; + ibest = d; + nbest = 1; + } + else if (d == ibest) + nbest++; + fdec = fdec->mNext; + } + + if (ibest == INT_MAX) + mErrors->Error(cexp->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching function call"); + else if (nbest > 1) + mErrors->Error(cexp->mLocation, ERRO_AMBIGUOUS_FUNCTION_CALL, "Ambiguous function call"); + else + { + cexp->mDecValue = dbest; + cexp->mDecType = dbest->mBase; + } + } + } +} + Expression* Parser::ParsePostfixExpression(void) { Expression* exp = ParseSimpleExpression(); @@ -2043,7 +2197,6 @@ Expression* Parser::ParsePostfixExpression(void) mInlineCall = false; nexp->mLeft = exp; - nexp->mDecType = exp->mDecType->mBase; if (mScanner->mToken != TK_CLOSE_PARENTHESIS) { nexp->mRight = ParseListExpression(); @@ -2054,6 +2207,10 @@ Expression* Parser::ParsePostfixExpression(void) nexp->mRight = nullptr; mScanner->NextToken(); } + + ResolveOverloadCall(exp, nexp->mRight); + nexp->mDecType = exp->mDecType->mBase; + exp = nexp; } else if (mScanner->mToken == TK_INC || mScanner->mToken == TK_DEC) @@ -4536,6 +4693,8 @@ void Parser::Parse(void) Expression* exp = ParseAssembler(); exp->mDecValue->mIdent = ident; + exp->mDecValue->mQualIdent = ident; + mScope->Insert(ident, exp->mDecValue); if (mScanner->mToken == TK_CLOSE_BRACE) diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 45277f4..7f5b660 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -39,7 +39,7 @@ protected: void ParsePragma(void); Declaration* ParseBaseTypeDeclaration(uint64 flags); - Declaration* ParseDeclaration(Declaration* pdec, bool variable, bool expression); + Declaration* ParseDeclaration(Declaration* pdec, bool variable, bool expression, Declaration * pthis = nullptr); Declaration* ParseStructDeclaration(uint64 flags, DecType dt); Declaration* CopyConstantInitializer(int offset, Declaration* dtype, Expression* exp); @@ -65,6 +65,9 @@ protected: Expression* ParseSwitchStatement(void); Expression* ParseQualify(Expression * exp); + + int OverloadDistance(Declaration* pdec, Expression* pexp); + void ResolveOverloadCall(Expression* cexp, Expression* pexp); Expression* ParseSimpleExpression(void); Expression* ParsePrefixExpression(void);