Function overloading in cpp mode

This commit is contained in:
drmortalwombat 2023-06-18 20:27:20 +02:00
parent f72048383a
commit b008d39eae
6 changed files with 236 additions and 39 deletions

View File

@ -85,8 +85,11 @@ Declaration * DeclarationScope::Insert(const Ident* ident, Declaration* dec)
return nullptr; return nullptr;
} }
Declaration* DeclarationScope::Lookup(const Ident* ident) Declaration* DeclarationScope::Lookup(const Ident* ident, ScopeLevel limit)
{ {
if (mLevel < limit)
return nullptr;
if (mHashSize > 0) if (mHashSize > 0)
{ {
int hm = mHashSize - 1; int hm = mHashSize - 1;
@ -900,6 +903,25 @@ bool Declaration::IsConstSame(const Declaration* dec) const
return false; 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 bool Declaration::IsSame(const Declaration* dec) const
{ {
if (this == dec) if (this == dec)

View File

@ -119,7 +119,7 @@ public:
const Ident* Mangle(const Ident* ident) const; const Ident* Mangle(const Ident* ident) const;
Declaration* Insert(const Ident* ident, Declaration* dec); 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); void End(const Location & loc);
@ -234,6 +234,7 @@ public:
bool IsSubType(const Declaration* dec) const; bool IsSubType(const Declaration* dec) const;
bool IsConstSame(const Declaration* dec) const; bool IsConstSame(const Declaration* dec) const;
bool IsSameValue(const Declaration* dec) const; bool IsSameValue(const Declaration* dec) const;
bool IsSameParams(const Declaration* dec) const;
bool IsIntegerType(void) const; bool IsIntegerType(void) const;
bool IsNumericType(void) const; bool IsNumericType(void) const;

View File

@ -73,6 +73,8 @@ enum ErrorID
ERRO_NOT_A_NAMESPACE, ERRO_NOT_A_NAMESPACE,
ERRO_NOT_A_BASE_CLASS, ERRO_NOT_A_BASE_CLASS,
ERRO_THIS_OUTSIDE_OF_METHOD, ERRO_THIS_OUTSIDE_OF_METHOD,
ERRO_NO_MATCHING_FUNCTION_CALL,
ERRO_AMBIGUOUS_FUNCTION_CALL,
ERRR_STACK_OVERFLOW, ERRR_STACK_OVERFLOW,
ERRR_INVALID_NUMBER, ERRR_INVALID_NUMBER,

View File

@ -18841,6 +18841,8 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
if (mEntryRequiredRegs[CPU_REG_A]) if (mEntryRequiredRegs[CPU_REG_A])
{ {
mIns.Insert(0, NativeCodeInstruction(mIns[0].mIns, ASMIT_TAX)); 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)); 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)); block->mIns.Insert(j, NativeCodeInstruction(ins.mIns, ASMIT_DEY));
yoffset--; yoffset--;
} }
while (yoffset < 0) while (yoffset < 0)
{ {
j++; j++;
@ -31397,8 +31400,11 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc)
} }
if (j + 1 == block->mIns.Size() && (ins.mLive & LIVE_CPU_REG_Z) && ins.ChangesAccuAndFlag()) 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)); block->mIns.Push(NativeCodeInstruction(ins.mIns, ASMIT_ORA, ASMIM_IMMEDIATE, 0));
} }
}
if (xoffset && xreg >= 0 && !(ins.mLive & LIVE_CPU_REG_X)) 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)); block->mIns.Insert(j, NativeCodeInstruction(ins.mIns, ASMIT_DEX));
xoffset--; xoffset--;
} }
while (xoffset < 0) while (xoffset < 0)
{ {
j++; j++;
@ -31416,8 +31423,11 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc)
} }
if (j + 1 == block->mIns.Size() && (ins.mLive & LIVE_CPU_REG_Z) && ins.ChangesAccuAndFlag()) 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)); block->mIns.Push(NativeCodeInstruction(ins.mIns, ASMIT_ORA, ASMIM_IMMEDIATE, 0));
} }
}
if (yreg >= 0) if (yreg >= 0)
ins.mLive |= LIVE_CPU_REG_Y; ins.mLive |= LIVE_CPU_REG_Y;

View File

@ -86,18 +86,21 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
if (mScanner->mToken == TK_OPEN_BRACE) if (mScanner->mToken == TK_OPEN_BRACE)
{ {
Declaration* othis = mThisPointer; Declaration* pthis = nullptr;
mThisPointer = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); if (mCompilerOptions & COPT_CPLUSPLUS)
mThisPointer->mFlags |= DTF_CONST | DTF_DEFINED; {
mThisPointer->mBase = dec; pthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER);
mThisPointer->mSize = 2; pthis->mFlags |= DTF_CONST | DTF_DEFINED;
pthis->mBase = dec;
pthis->mSize = 2;
}
mScanner->NextToken(); mScanner->NextToken();
Declaration* mlast = nullptr; Declaration* mlast = nullptr;
for (;;) for (;;)
{ {
Declaration* mdec = ParseDeclaration(nullptr, false, false); Declaration* mdec = ParseDeclaration(nullptr, false, false, pthis);
mdec->mQualIdent = dec->mScope->Mangle(mdec->mIdent); mdec->mQualIdent = dec->mScope->Mangle(mdec->mIdent);
@ -115,10 +118,29 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
if (mCompilerOptions & COPT_NATIVE) if (mCompilerOptions & COPT_NATIVE)
mdec->mFlags |= DTF_NATIVE; mdec->mFlags |= DTF_NATIVE;
if (dec->mScope->Insert(mdec->mIdent, mdec)) Declaration* pdec = dec->mScope->Insert(mdec->mIdent, mdec);
mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent);
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); mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent);
if (!(mdec->mFlags & DTF_DEFINED)) if (!(mdec->mFlags & DTF_DEFINED))
@ -177,8 +199,6 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
dec->mParams = nullptr; dec->mParams = nullptr;
dec->mFlags |= DTF_DEFINED; dec->mFlags |= DTF_DEFINED;
mThisPointer = othis;
} }
return dec; return dec;
@ -1104,7 +1124,7 @@ Expression* Parser::ParseInitExpression(Declaration* dtype)
return exp; 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; bool definingType = false;
uint64 storageFlags = 0, typeFlags = 0; uint64 storageFlags = 0, typeFlags = 0;
@ -1266,13 +1286,13 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
} }
else 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); Declaration* adec = new Declaration(ndec->mLocation, DT_ARGUMENT);
adec->mVarIndex = 0; adec->mVarIndex = 0;
adec->mOffset = 0; adec->mOffset = 0;
adec->mBase = mThisPointer; adec->mBase = pthis;
adec->mSize = adec->mBase->mSize; adec->mSize = adec->mBase->mSize;
adec->mNext = ndec->mBase->mParams; adec->mNext = ndec->mBase->mParams;
adec->mIdent = adec->mQualIdent = Ident::Unique("this"); adec->mIdent = adec->mQualIdent = Ident::Unique("this");
@ -1348,6 +1368,22 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
ndec->mBase->mFlags |= DTF_FUNC_THIS; ndec->mBase->mFlags |= DTF_FUNC_THIS;
} }
if (mCompilerOptions & COPT_CPLUSPLUS)
{
Declaration* pcdec = nullptr;
while (pdec && !ndec->mBase->IsSameParams(pdec->mBase))
{
pcdec = pdec;
pdec = pdec->mNext;
}
if (!pdec)
pcdec->mNext = ndec;
}
if (pdec)
{
if (!ndec->mBase->IsSame(pdec->mBase)) if (!ndec->mBase->IsSame(pdec->mBase))
mErrors->Error(ndec->mLocation, EERR_DECLARATION_DIFFERS, "Function declaration differs", ndec->mIdent); 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)) else if (ndec->mFlags & ~pdec->mFlags & (DTF_HWINTERRUPT | DTF_INTERRUPT | DTF_FASTCALL | DTF_NATIVE))
@ -1372,6 +1408,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
ndec = pdec; ndec = pdec;
} }
}
else if (ndec->mFlags & DTF_EXTERN) else if (ndec->mFlags & DTF_EXTERN)
{ {
if (!ndec->mBase->IsSame(pdec->mBase)) if (!ndec->mBase->IsSame(pdec->mBase))
@ -1772,7 +1809,7 @@ Expression* Parser::ParseSimpleExpression(void)
mScanner->NextToken(); mScanner->NextToken();
break; break;
case TK_IDENT: case TK_IDENT:
if (mThisPointer) if (mThisPointer && !mScope->Lookup(mScanner->mTokenIdent, SLEVEL_FUNCTION))
{ {
dec = mThisPointer->mBase->mBase->mScope->Lookup(mScanner->mTokenIdent); dec = mThisPointer->mBase->mBase->mScope->Lookup(mScanner->mTokenIdent);
if (dec) if (dec)
@ -1969,10 +2006,14 @@ Expression* Parser::ParseQualify(Expression* exp)
Expression* texp = new Expression(nexp->mLocation, EX_PREFIX); Expression* texp = new Expression(nexp->mLocation, EX_PREFIX);
texp->mToken = TK_BINARY_AND; texp->mToken = TK_BINARY_AND;
texp->mLeft = exp; 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) if (nexp->mRight)
{ {
Expression* lexp = new Expression(nexp->mLocation, EX_SEQUENCE); Expression* lexp = new Expression(nexp->mLocation, EX_LIST);
lexp->mLeft = texp; lexp->mLeft = texp;
lexp->mRight = nexp->mRight; lexp->mRight = nexp->mRight;
nexp->mRight = lexp; nexp->mRight = lexp;
@ -1980,6 +2021,9 @@ Expression* Parser::ParseQualify(Expression* exp)
else else
nexp->mRight = texp; nexp->mRight = texp;
ResolveOverloadCall(nexp->mLeft, nexp->mRight);
nexp->mDecType = nexp->mLeft->mDecType->mBase;
exp = nexp; exp = nexp;
} }
} }
@ -1999,6 +2043,116 @@ Expression* Parser::ParseQualify(Expression* exp)
return 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* Parser::ParsePostfixExpression(void)
{ {
Expression* exp = ParseSimpleExpression(); Expression* exp = ParseSimpleExpression();
@ -2043,7 +2197,6 @@ Expression* Parser::ParsePostfixExpression(void)
mInlineCall = false; mInlineCall = false;
nexp->mLeft = exp; nexp->mLeft = exp;
nexp->mDecType = exp->mDecType->mBase;
if (mScanner->mToken != TK_CLOSE_PARENTHESIS) if (mScanner->mToken != TK_CLOSE_PARENTHESIS)
{ {
nexp->mRight = ParseListExpression(); nexp->mRight = ParseListExpression();
@ -2054,6 +2207,10 @@ Expression* Parser::ParsePostfixExpression(void)
nexp->mRight = nullptr; nexp->mRight = nullptr;
mScanner->NextToken(); mScanner->NextToken();
} }
ResolveOverloadCall(exp, nexp->mRight);
nexp->mDecType = exp->mDecType->mBase;
exp = nexp; exp = nexp;
} }
else if (mScanner->mToken == TK_INC || mScanner->mToken == TK_DEC) else if (mScanner->mToken == TK_INC || mScanner->mToken == TK_DEC)
@ -4536,6 +4693,8 @@ void Parser::Parse(void)
Expression* exp = ParseAssembler(); Expression* exp = ParseAssembler();
exp->mDecValue->mIdent = ident; exp->mDecValue->mIdent = ident;
exp->mDecValue->mQualIdent = ident;
mScope->Insert(ident, exp->mDecValue); mScope->Insert(ident, exp->mDecValue);
if (mScanner->mToken == TK_CLOSE_BRACE) if (mScanner->mToken == TK_CLOSE_BRACE)

View File

@ -39,7 +39,7 @@ protected:
void ParsePragma(void); void ParsePragma(void);
Declaration* ParseBaseTypeDeclaration(uint64 flags); 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* ParseStructDeclaration(uint64 flags, DecType dt);
Declaration* CopyConstantInitializer(int offset, Declaration* dtype, Expression* exp); Declaration* CopyConstantInitializer(int offset, Declaration* dtype, Expression* exp);
@ -66,6 +66,9 @@ protected:
Expression* ParseQualify(Expression * exp); Expression* ParseQualify(Expression * exp);
int OverloadDistance(Declaration* pdec, Expression* pexp);
void ResolveOverloadCall(Expression* cexp, Expression* pexp);
Expression* ParseSimpleExpression(void); Expression* ParseSimpleExpression(void);
Expression* ParsePrefixExpression(void); Expression* ParsePrefixExpression(void);
Expression* ParsePostfixExpression(void); Expression* ParsePostfixExpression(void);