diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 9a37e7f..4df17c1 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -660,6 +660,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo case EX_ASSIGNMENT: ldec = Analyze(exp->mLeft, procDec, true); rdec = Analyze(exp->mRight, procDec, false); + if (exp->mLeft->mType == EX_VARIABLE && exp->mRight->mType == EX_CALL && exp->mLeft->mDecType->mType == DT_TYPE_STRUCT) + exp->mLeft->mDecValue->mFlags |= DTF_VAR_ALIASING; RegisterProc(rdec); return ldec; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 1a1b6cd..69ae93b 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -3095,6 +3095,11 @@ void InterInstruction::CollectLocalAddressTemps(GrowingIntArray& localTable, Gro nparams = mSrc[1].mVarIndex + 1; } } + else if (mSrc[1].mTemp >= 0) + { + localTable[mDst.mTemp] = localTable[mSrc[1].mTemp]; + paramTable[mDst.mTemp] = paramTable[mSrc[1].mTemp]; + } } else if (mCode == IC_LOAD_TEMPORARY) { @@ -9918,6 +9923,39 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& else nins = ins; } + else if (ins->mCode == IC_CALL_NATIVE && ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mLinkerObject && ins->mSrc[0].mLinkerObject->mProc && ins->mSrc[0].mLinkerObject->mProc->mGlobalsChecked) + { + InterCodeProcedure* proc = ins->mSrc[0].mLinkerObject->mProc; + + int j = 0, k = 0; + while (j < mLoadStoreInstructions.Size()) + { + InterOperand* op = nullptr; + + if (mLoadStoreInstructions[j]->mCode == IC_LOAD) + op = mLoadStoreInstructions[j]->mSrc + 0; + else if (mLoadStoreInstructions[j]->mCode == IC_STORE) + op = mLoadStoreInstructions[j]->mSrc + 1; + + bool flush = false; + if (op) + { + if (op->mTemp >= 0) + flush = proc->mStoresIndirect; + else if (op->mMemory == IM_FFRAME || op->mMemory == IM_FRAME) + flush = true; + else if (op->mMemory == IM_GLOBAL) + flush = proc->ModifiesGlobal(op->mVarIndex); + else + flush = true; + } + + if (!flush) + mLoadStoreInstructions[k++] = mLoadStoreInstructions[j]; + j++; + } + mLoadStoreInstructions.SetSize(k); + } else if (HasSideEffect(ins->mCode)) flushMem = true; @@ -11298,7 +11336,7 @@ void InterCodeBasicBlock::CollectStaticStack(LinkerObject* lobj, const GrowingVa for (int i = 0; i < mInstructions.Size(); i++) { - if (mInstructions[i]->mCode == IC_CALL || mInstructions[i]->mCode == IC_CALL_NATIVE) + if ((mInstructions[i]->mCode == IC_CALL || mInstructions[i]->mCode == IC_CALL_NATIVE) && mInstructions[i]->mSrc[0].mLinkerObject->mStackSection) lobj->mStackSection->mSections.Push(mInstructions[i]->mSrc[0].mLinkerObject->mStackSection); if (mInstructions[i]->mCode == IC_LOAD) @@ -15350,6 +15388,74 @@ void InterCodeBasicBlock::CheckValueReturn(void) } } +void InterCodeBasicBlock::CollectGlobalReferences(NumberSet& referencedGlobals, NumberSet& modifiedGlobals, bool& storesIndirect, bool& loadsIndirect, bool& globalsChecked) +{ + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i < mInstructions.Size(); i++) + { + InterInstruction* ins = mInstructions[i]; + + switch (ins->mCode) + { + case IC_LOAD: + if (ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mMemory == IM_GLOBAL && ins->mSrc[0].mVarIndex >= 0) + referencedGlobals += ins->mSrc[0].mVarIndex; + else if (ins->mSrc[0].mTemp >= 0) + loadsIndirect = true; + break; + case IC_STORE: + if (ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mMemory == IM_GLOBAL && ins->mSrc[1].mVarIndex >= 0) + { + referencedGlobals += ins->mSrc[1].mVarIndex; + modifiedGlobals += ins->mSrc[1].mVarIndex; + } + else if (ins->mSrc[1].mTemp >= 0) + storesIndirect = true; + break; + case IC_COPY: + case IC_STRCPY: + if (ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mMemory == IM_GLOBAL && ins->mSrc[0].mVarIndex >= 0) + referencedGlobals += ins->mSrc[0].mVarIndex; + else if (ins->mSrc[0].mTemp >= 0) + loadsIndirect = true; + if (ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mMemory == IM_GLOBAL && ins->mSrc[1].mVarIndex >= 0) + { + referencedGlobals += ins->mSrc[1].mVarIndex; + modifiedGlobals += ins->mSrc[1].mVarIndex; + } + else if (ins->mSrc[1].mTemp >= 0) + storesIndirect = true; + break; + case IC_CALL: + case IC_CALL_NATIVE: + if (ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mLinkerObject && ins->mSrc[0].mLinkerObject->mProc) + { + InterCodeProcedure* proc = ins->mSrc[0].mLinkerObject->mProc; + if (proc->mGlobalsChecked) + { + if (proc->mStoresIndirect) + storesIndirect = true; + if (proc->mLoadsIndirect) + loadsIndirect = true; + referencedGlobals |= proc->mReferencedGlobals; + modifiedGlobals |= proc->mModifiedGlobals; + } + else + globalsChecked = false; + } + else + globalsChecked = false; + break; + } + } + + if (mTrueJump) mTrueJump->CollectGlobalReferences(referencedGlobals, modifiedGlobals, storesIndirect, loadsIndirect, globalsChecked); + if (mFalseJump) mFalseJump->CollectGlobalReferences(referencedGlobals, modifiedGlobals, storesIndirect, loadsIndirect, globalsChecked); + } +} void InterCodeBasicBlock::WarnUsedUndefinedVariables(void) { @@ -15707,7 +15813,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false), mSaveTempsLinkerObject(nullptr), mValueReturn(false), mFramePointer(false), mCheckUnreachable(true), mReturnType(IT_NONE), mCheapInline(false), - mDeclaration(nullptr) + mDeclaration(nullptr), mGlobalsChecked(false) { mID = mModule->mProcedures.Size(); mModule->mProcedures.Push(this); @@ -16551,7 +16657,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "card_color"); mEntryBlock = mBlocks[0]; @@ -17173,6 +17279,7 @@ void InterCodeProcedure::Close(void) #if 1 ResetVisited(); + if (!mInterruptCalled && !mDynamicStack && mNativeProcedure && mEntryBlock->CheckStaticStack()) { mLinkerObject->mFlags |= LOBJF_STATIC_STACK; @@ -17379,6 +17486,18 @@ void InterCodeProcedure::Close(void) } } + if (mTempSize <= BC_REG_TMP_SAVED - BC_REG_TMP && !(mLinkerObject->mFlags & LOBJF_STATIC_STACK) && mLeafProcedure) + { + bool hasLocals = false; + + for (int i = 0; i < mLocalVars.Size(); i++) + if (mLocalVars[i] && mLocalVars[i]->mUsed) + hasLocals = true; + + if (!hasLocals) + mLinkerObject->mFlags |= LOBJF_STATIC_STACK; + } + if (!mEntryBlock->mTrueJump) { int nconst = 0, nvariables = 0, nparams = 0, ncalls = 0, nret = 0, nother = 0, nops = 0; @@ -17449,6 +17568,15 @@ void InterCodeProcedure::Close(void) if (nother == 0 && ncalls <= 1 && nret == 1 && nconst <= 1 + nparams && nops <= 1 + nparams) mCheapInline = true; } + + mGlobalsChecked = true; + mStoresIndirect = false; + mLoadsIndirect = false; + mReferencedGlobals.Reset(mModule->mGlobalVars.Size()); + mModifiedGlobals.Reset(mModule->mGlobalVars.Size()); + + ResetVisited(); + mEntryBlock->CollectGlobalReferences(mReferencedGlobals, mModifiedGlobals, mStoresIndirect, mLoadsIndirect, mGlobalsChecked); } void InterCodeProcedure::AddCalledFunction(InterCodeProcedure* proc) @@ -17778,6 +17906,36 @@ void InterCodeProcedure::MergeBasicBlocks(void) } +bool InterCodeProcedure::ReferencesGlobal(int varindex) +{ + if (mGlobalsChecked) + { + if (mModule->mGlobalVars[varindex]->mAliased) + return mLoadsIndirect || mStoresIndirect; + else if (varindex < mReferencedGlobals.Size()) + return mReferencedGlobals[varindex]; + else + return false; + } + else + return true; +} + +bool InterCodeProcedure::ModifiesGlobal(int varindex) +{ + if (mGlobalsChecked) + { + if (mModule->mGlobalVars[varindex]->mAliased) + return mStoresIndirect; + else if (varindex < mModifiedGlobals.Size()) + return mModifiedGlobals[varindex]; + else + return false; + } + else + return true; +} + void InterCodeProcedure::BuildLoopPrefix(void) { ResetVisited(); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index e15a0f9..75845db 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -576,6 +576,8 @@ public: void WarnUsedUndefinedVariables(void); void CheckValueReturn(void); + void CollectGlobalReferences(NumberSet& referencedGlobals, NumberSet& modifiedGlobals, bool & storesIndirect, bool & loadsIndirect, bool & globalsChecked); + }; class InterCodeProcedure @@ -614,6 +616,9 @@ public: InterType mReturnType; uint64 mCompilerOptions; + bool mLoadsIndirect, mStoresIndirect, mGlobalsChecked; + NumberSet mReferencedGlobals, mModifiedGlobals; + InterCodeProcedure(InterCodeModule * module, const Location & location, const Ident * ident, LinkerObject* linkerObject); ~InterCodeProcedure(void); @@ -631,6 +636,9 @@ public: void MapCallerSavedTemps(void); + bool ReferencesGlobal(int varindex); + bool ModifiesGlobal(int varindex); + void MapVariables(void); void ReduceTemporaries(void); void Disassemble(FILE* file); diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index c2a23cf..84eead1 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -43,12 +43,14 @@ void LinkerObject::AddReference(const LinkerReference& ref) mReferences.Push(nref); } -LinkerReference* LinkerObject::FindReference(int offset) +LinkerReference* LinkerObject::FindReference(int64 offset) { for (int i = 0; i < mReferences.Size(); i++) { if (mReferences[i]->mOffset == offset) return mReferences[i]; + else if ((mReferences[i]->mFlags & LREF_LOWBYTE) && (mReferences[i]->mFlags & LREF_HIGHBYTE) && mReferences[i]->mOffset + 1 == offset) + return mReferences[i]; } return nullptr; diff --git a/oscar64/Linker.h b/oscar64/Linker.h index ab6b3a8..ff9affa 100644 --- a/oscar64/Linker.h +++ b/oscar64/Linker.h @@ -202,7 +202,7 @@ public: GrowingArray mReferences; - LinkerReference* FindReference(int offset); + LinkerReference* FindReference(int64 offset); void AddReference(const LinkerReference& ref); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index ffb3809..5047cc1 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -7133,10 +7133,34 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, if (size <= msize) { - for (int i = 0; i < size; i++) + LinkerObject* slo = ins->mSrc[0].mLinkerObject; + if (slo && (slo->mFlags & LOBJF_CONST)) { - block->mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + offset + i * sstride, ins->mSrc[0].mLinkerObject, flags)); - block->mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + offset + i * dstride, ins->mSrc[1].mLinkerObject, flags)); + + for (int i = 0; i < size; i++) + { + int64 si = ins->mSrc[0].mIntConst + offset + i * sstride; + + LinkerReference* lr = slo->FindReference(si); + if (lr) + { + if ((lr->mFlags & LREF_LOWBYTE) && lr->mOffset == si) + block->mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, lr->mRefOffset, lr->mRefObject, NCIF_LOWER)); + else + block->mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, lr->mRefOffset, lr->mRefObject, NCIF_UPPER)); + } + else + block->mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, slo->mData[si])); + block->mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + offset + i * dstride, ins->mSrc[1].mLinkerObject, flags)); + } + } + else + { + for (int i = 0; i < size; i++) + { + block->mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + offset + i * sstride, ins->mSrc[0].mLinkerObject, flags)); + block->mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + offset + i * dstride, ins->mSrc[1].mLinkerObject, flags)); + } } } else @@ -7156,6 +7180,40 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, return block; } + else if ((ins->mSrc[0].mMemory == IM_GLOBAL || ins->mSrc[0].mMemory == IM_ABSOLUTE) && (ins->mSrc[1].mMemory == IM_FPARAM || ins->mSrc[1].mMemory == IM_FFRAME)) + { + LinkerObject* slo = ins->mSrc[0].mLinkerObject; + if (slo && (slo->mFlags & LOBJF_CONST)) + { + + for (int i = 0; i < size; i++) + { + int64 si = ins->mSrc[0].mIntConst + i * sstride; + + LinkerReference* lr = slo->FindReference(si); + if (lr) + { + if ((lr->mFlags & LREF_LOWBYTE) && lr->mOffset == si) + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, lr->mRefOffset, lr->mRefObject, NCIF_LOWER)); + else + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, lr->mRefOffset, lr->mRefObject, NCIF_UPPER)); + } + else + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, slo->mData[si])); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + i * dstride)); + } + } + else + { + for (int i = 0; i < size; i++) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + i * sstride, ins->mSrc[0].mLinkerObject, flags)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + i * dstride)); + } + } + + return this; + } } #endif