Propagate static stack usage through recursions

This commit is contained in:
drmortalwombat 2023-05-28 14:30:46 +02:00
parent a4faf204cb
commit d6faefb5fc
4 changed files with 88 additions and 21 deletions

View File

@ -602,6 +602,7 @@ bool Compiler::GenerateCode(void)
} }
mGlobalAnalyzer->CheckInterrupt(); mGlobalAnalyzer->CheckInterrupt();
mGlobalAnalyzer->MarkRecursions();
mGlobalAnalyzer->AutoInline(); mGlobalAnalyzer->AutoInline();
mGlobalAnalyzer->AutoZeroPage(mCompilationUnits->mSectionZeroPage, regionZeroPage->mEnd - regionZeroPage->mStart); mGlobalAnalyzer->AutoZeroPage(mCompilationUnits->mSectionZeroPage, regionZeroPage->mEnd - regionZeroPage->mStart);
if (mCompilerOptions & COPT_VERBOSE3) if (mCompilerOptions & COPT_VERBOSE3)

View File

@ -208,34 +208,91 @@ void GlobalAnalyzer::AutoInline(void)
for (int i = 0; i < mFunctions.Size(); i++) for (int i = 0; i < mFunctions.Size(); i++)
{ {
CheckFastcall(mFunctions[i]); CheckFastcall(mFunctions[i], true);
} }
} }
void GlobalAnalyzer::CheckFastcall(Declaration* procDec) bool GlobalAnalyzer::MarkCycle(Declaration* rootDec, Declaration* procDec)
{ {
if (!(procDec->mBase->mFlags & DTF_FASTCALL) && !(procDec->mBase->mFlags & DTF_STACKCALL) && (procDec->mType == DT_CONST_FUNCTION)) if (rootDec == procDec)
return true;
if (!(procDec->mFlags & DTF_FUNC_ANALYZING))
{ {
if (!(procDec->mBase->mFlags & DTF_VARIADIC) && !(procDec->mFlags & DTF_FUNC_VARIABLE) && !(procDec->mFlags & DTF_FUNC_RECURSIVE) && !(procDec->mFlags & DTF_DYNSTACK)) procDec->mFlags |= DTF_FUNC_ANALYZING;
bool cycle = false;
for (int i = 0; i < procDec->mCalled.Size(); i++)
{ {
int nbase = 0; if (MarkCycle(rootDec, procDec->mCalled[i]))
for (int i = 0; i < procDec->mCalled.Size(); i++) cycle = true;
{ }
Declaration* cf = procDec->mCalled[i]; if (cycle)
procDec->mFlags |= DTF_FUNC_RECURSIVE;
CheckFastcall(cf); procDec->mFlags &= ~DTF_FUNC_ANALYZING;
cf = cf->mBase; return cycle;
if (cf->mFlags & DTF_FASTCALL) }
{
int n = cf->mFastCallBase + cf->mFastCallSize;
if (n > nbase)
nbase = n;
}
else
nbase = 1000;
}
return false;
}
void GlobalAnalyzer::MarkRecursions(void)
{
for (int i = 0; i < mFunctions.Size(); i++)
{
Declaration* cf = mFunctions[i];
for (int j = 0; j < cf->mCalled.Size(); j++)
{
if (MarkCycle(cf, cf->mCalled[j]))
cf->mFlags |= DTF_FUNC_RECURSIVE;
}
}
}
void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
{
if (!(procDec->mBase->mFlags & DTF_FASTCALL) && !(procDec->mBase->mFlags & DTF_STACKCALL) && (procDec->mType == DT_CONST_FUNCTION) && !(procDec->mFlags & DTF_FUNC_ANALYZING))
{
procDec->mFlags |= DTF_FUNC_ANALYZING;
int nbase = 0;
for (int i = 0; i < procDec->mCalled.Size(); i++)
{
Declaration* cf = procDec->mCalled[i];
if (cf->mType == DT_TYPE_FUNCTION)
procDec->mFlags |= DTF_DYNSTACK;
CheckFastcall(cf, false);
// if (!(cf->mBase->mFlags & DTF_FASTCALL))
// procDec->mBase->mFlags |= DTF_STACKCALL;
cf = cf->mBase;
int n = cf->mFastCallBase + cf->mFastCallSize;
if (n > nbase)
nbase = n;
}
procDec->mFastCallBase = nbase;
procDec->mFastCallSize = 0;
procDec->mBase->mFastCallBase = nbase;
procDec->mBase->mFastCallSize = 0;
procDec->mFlags &= ~DTF_FUNC_ANALYZING;
if (procDec->mBase->mFlags & DTF_STACKCALL)
{
procDec->mBase->mFlags |= DTF_STACKCALL;
}
else if (procDec->mFlags & DTF_FUNC_RECURSIVE)
{
if (head)
procDec->mBase->mFlags |= DTF_STACKCALL;
}
else if (!(procDec->mBase->mFlags & DTF_VARIADIC) && !(procDec->mFlags & DTF_FUNC_VARIABLE) && !(procDec->mFlags & DTF_DYNSTACK))
{
int nparams = 0, npalign = 0; int nparams = 0, npalign = 0;
int numfpzero = BC_REG_FPARAMS_END - BC_REG_FPARAMS; int numfpzero = BC_REG_FPARAMS_END - BC_REG_FPARAMS;
int fplimit = numfpzero; int fplimit = numfpzero;
@ -410,6 +467,9 @@ void GlobalAnalyzer::AnalyzeAssembler(Expression* exp, Declaration* procDec)
void GlobalAnalyzer::AnalyzeGlobalVariable(Declaration* dec) void GlobalAnalyzer::AnalyzeGlobalVariable(Declaration* dec)
{ {
while (dec->mType == DT_VARIABLE_REF)
dec = dec->mBase;
dec->mUseCount++; dec->mUseCount++;
if (!(dec->mFlags & DTF_ANALYZED)) if (!(dec->mFlags & DTF_ANALYZED))

View File

@ -12,9 +12,10 @@ public:
void DumpCallGraph(void); void DumpCallGraph(void);
void AutoInline(void); void AutoInline(void);
void CheckFastcall(Declaration* procDec); void CheckFastcall(Declaration* procDec, bool head);
void CheckInterrupt(void); void CheckInterrupt(void);
void AutoZeroPage(LinkerSection * lszp, int zpsize); void AutoZeroPage(LinkerSection * lszp, int zpsize);
void MarkRecursions(void);
void AnalyzeProcedure(Expression* exp, Declaration* procDec); void AnalyzeProcedure(Expression* exp, Declaration* procDec);
void AnalyzeAssembler(Expression* exp, Declaration* procDec); void AnalyzeAssembler(Expression* exp, Declaration* procDec);
@ -31,6 +32,8 @@ protected:
Declaration* Analyze(Expression* exp, Declaration* procDec, bool lhs); Declaration* Analyze(Expression* exp, Declaration* procDec, bool lhs);
bool MarkCycle(Declaration* rootDec, Declaration* procDec);
uint64 GetProcFlags(Declaration* to) const; uint64 GetProcFlags(Declaration* to) const;
void RegisterCall(Declaration* from, Declaration* to); void RegisterCall(Declaration* from, Declaration* to);
void RegisterProc(Declaration* to); void RegisterProc(Declaration* to);

View File

@ -414,7 +414,10 @@ void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration*
{ {
if (dec->mValue->mType == EX_CONSTANT) if (dec->mValue->mType == EX_CONSTANT)
{ {
BuildInitializer(mod, d, 0, dec->mValue->mDecValue, var); if (dec->mBase->CanAssign(dec->mValue->mDecType))
BuildInitializer(mod, d, 0, dec->mValue->mDecValue, var);
else
mErrors->Error(dec->mLocation, EERR_INCOMPATIBLE_TYPES, "Incompatible constant initializer");
} }
else else
mErrors->Error(dec->mLocation, EERR_CONSTANT_INITIALIZER, "Non constant initializer"); mErrors->Error(dec->mLocation, EERR_CONSTANT_INITIALIZER, "Non constant initializer");