diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 61328c7..2cb4b03 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -602,6 +602,7 @@ bool Compiler::GenerateCode(void) } mGlobalAnalyzer->CheckInterrupt(); + mGlobalAnalyzer->MarkRecursions(); mGlobalAnalyzer->AutoInline(); mGlobalAnalyzer->AutoZeroPage(mCompilationUnits->mSectionZeroPage, regionZeroPage->mEnd - regionZeroPage->mStart); if (mCompilerOptions & COPT_VERBOSE3) diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 0553faf..226a784 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -208,34 +208,91 @@ void GlobalAnalyzer::AutoInline(void) 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; - for (int i = 0; i < procDec->mCalled.Size(); i++) - { - Declaration* cf = procDec->mCalled[i]; + if (MarkCycle(rootDec, procDec->mCalled[i])) + cycle = true; + } + if (cycle) + procDec->mFlags |= DTF_FUNC_RECURSIVE; - CheckFastcall(cf); + procDec->mFlags &= ~DTF_FUNC_ANALYZING; - cf = cf->mBase; - if (cf->mFlags & DTF_FASTCALL) - { - int n = cf->mFastCallBase + cf->mFastCallSize; - if (n > nbase) - nbase = n; - } - else - nbase = 1000; - } + return cycle; + } + 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 numfpzero = BC_REG_FPARAMS_END - BC_REG_FPARAMS; int fplimit = numfpzero; @@ -410,6 +467,9 @@ void GlobalAnalyzer::AnalyzeAssembler(Expression* exp, Declaration* procDec) void GlobalAnalyzer::AnalyzeGlobalVariable(Declaration* dec) { + while (dec->mType == DT_VARIABLE_REF) + dec = dec->mBase; + dec->mUseCount++; if (!(dec->mFlags & DTF_ANALYZED)) diff --git a/oscar64/GlobalAnalyzer.h b/oscar64/GlobalAnalyzer.h index d657a36..daee81f 100644 --- a/oscar64/GlobalAnalyzer.h +++ b/oscar64/GlobalAnalyzer.h @@ -12,9 +12,10 @@ public: void DumpCallGraph(void); void AutoInline(void); - void CheckFastcall(Declaration* procDec); + void CheckFastcall(Declaration* procDec, bool head); void CheckInterrupt(void); void AutoZeroPage(LinkerSection * lszp, int zpsize); + void MarkRecursions(void); void AnalyzeProcedure(Expression* exp, Declaration* procDec); void AnalyzeAssembler(Expression* exp, Declaration* procDec); @@ -31,6 +32,8 @@ protected: Declaration* Analyze(Expression* exp, Declaration* procDec, bool lhs); + bool MarkCycle(Declaration* rootDec, Declaration* procDec); + uint64 GetProcFlags(Declaration* to) const; void RegisterCall(Declaration* from, Declaration* to); void RegisterProc(Declaration* to); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 7bf4420..ea3437b 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -414,7 +414,10 @@ void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration* { 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 mErrors->Error(dec->mLocation, EERR_CONSTANT_INITIALIZER, "Non constant initializer");