From f6c78d57ef1e32ef7b5a56f8e9bafd3d67c91316 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 2 Oct 2024 18:27:20 +0200 Subject: [PATCH] Add __forceinline storage specifier --- oscar64/ByteCodeGenerator.cpp | 2 +- oscar64/Declaration.h | 2 ++ oscar64/Errors.h | 1 + oscar64/GlobalAnalyzer.cpp | 4 ++-- oscar64/InterCode.cpp | 29 ++++++++++++++++++++++++++--- oscar64/InterCode.h | 2 ++ oscar64/InterCodeGenerator.cpp | 14 ++++++++++---- oscar64/Parser.cpp | 10 ++++++++-- oscar64/Scanner.cpp | 3 +++ oscar64/Scanner.h | 1 + 10 files changed, 56 insertions(+), 12 deletions(-) diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp index bdc5d88..275694c 100644 --- a/oscar64/ByteCodeGenerator.cpp +++ b/oscar64/ByteCodeGenerator.cpp @@ -6548,7 +6548,7 @@ void ByteCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedure { mID = proc->mID; - mNumBlocks = proc->mBlocks.Size(); + mNumBlocks = proc->mNumBlocks; tblocks = new ByteCodeBasicBlock * [mNumBlocks]; for (int i = 0; i < mNumBlocks; i++) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 1af0fe2..5a2bb22 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -104,6 +104,7 @@ static const uint64 DTF_CONSTEXPR = (1ULL << 31); static const uint64 DTF_AUTO_TEMPLATE = (1ULL << 32); static const uint64 DTF_BANK_INLAY = (1ULL << 33); static const uint64 DTF_PURE_VIRTUAL = (1ULL << 34); +static const uint64 DTF_FORCE_INLINE = (1ULL << 35); static const uint64 DTF_FUNC_VARIABLE = (1ULL << 36); static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 37); @@ -127,6 +128,7 @@ static const uint64 DTF_DEPRECATED = (1ULL << 50); static const uint64 DTF_FUNC_NO_RETURN = (1ULL << 51); + class Declaration; enum ScopeLevel diff --git a/oscar64/Errors.h b/oscar64/Errors.h index aea4aa0..7d28af1 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -43,6 +43,7 @@ enum ErrorID EWARN_INVALID_VALUE_RANGE, EWARN_DEFAULT_COPY_DEPRECATED, EWARN_INSUFFICIENT_MEMORY, + EWARN_FUNCTION_NOT_INLINED, EERR_GENERIC = 3000, EERR_FILE_NOT_FOUND, diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 59663d4..7dd8ed2 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -161,7 +161,7 @@ int GlobalAnalyzer::CallerInvokes(Declaration* called) int GlobalAnalyzer::CallerInvokes(Declaration* caller, Declaration* called) { int n = 1; - if (caller->mType == DT_CONST_FUNCTION && (caller->mFlags & (DTF_INLINE | DTF_REQUEST_INLINE)) && !(caller->mFlags & DTF_PREVENT_INLINE) && !(caller->mFlags & DTF_FUNC_RECURSIVE) && !(caller->mFlags & DTF_FUNC_VARIABLE) && !(caller->mFlags & DTF_EXPORT)) + if (caller->mType == DT_CONST_FUNCTION && (caller->mFlags & (DTF_INLINE | DTF_FORCE_INLINE | DTF_REQUEST_INLINE)) && !(caller->mFlags & DTF_PREVENT_INLINE) && !(caller->mFlags & DTF_FUNC_RECURSIVE) && !(caller->mFlags & DTF_FUNC_VARIABLE) && !(caller->mFlags & DTF_EXPORT)) n = CallerInvokes(caller); return n > 1 ? n : 1; } @@ -206,7 +206,7 @@ void GlobalAnalyzer::AutoInline(void) // printf("CHECK INLINING %s (%d) %d * (%d - 1)\n", f->mIdent->mString, f->mComplexity, cost, invokes); bool doinline = false; - if ((f->mCompilerOptions & COPT_OPTIMIZE_INLINE) && (f->mFlags & DTF_REQUEST_INLINE)) + if ((f->mCompilerOptions & COPT_OPTIMIZE_INLINE) && (f->mFlags & DTF_REQUEST_INLINE) || (f->mFlags & DTF_FORCE_INLINE)) doinline = true; if (f->mLocalSize < 100) { diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 6da97bb..72e13f6 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -5844,7 +5844,7 @@ InterCodeBasicBlock::InterCodeBasicBlock(InterCodeProcedure * proc) mUnreachable = false; mValueRangeValid = false; - mIndex = proc->mBlocks.Size(); + mIndex = proc->mNumBlocks++; proc->mBlocks.Push(this); } @@ -7441,6 +7441,8 @@ bool InterCodeBasicBlock::EarlyBranchElimination(const GrowingInstructionPtrArra if (cins->mConst.mType == IT_BOOL) { mInstructions[sz - 1]->mCode = IC_JUMP; + mInstructions[sz - 1]->mNumOperands = 0; + if (cins->mConst.mIntConst) mFalseJump->mNumEntries--; else @@ -21668,7 +21670,7 @@ void InterCodeBasicBlock::WarnUnreachable(void) InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & location, const Ident* ident, LinkerObject * linkerObject) - : mTemporaries(IT_NONE), mBlocks(nullptr), mLocation(location), mTempOffset(-1), mTempSizes(0), + : mTemporaries(IT_NONE), mBlocks(nullptr), mLocation(location), mTempOffset(-1), mTempSizes(0), mNumBlocks(0), mRenameTable(-1), mRenameUnionTable(-1), mGlobalRenameTable(-1), mValueForwardingTable(nullptr), mLocalVars(nullptr), mParamVars(nullptr), mModule(mod), mIdent(ident), mLinkerObject(linkerObject), @@ -21809,7 +21811,10 @@ void InterCodeProcedure::EarlyBranchElimination(void) ResetVisited(); while (mEntryBlock->EarlyBranchElimination(ctemps)) - {} + { + BuildTraces(true); + TrimBlocks(); + } } void InterCodeProcedure::BuildTraces(bool expand, bool dominators, bool compact) @@ -21847,6 +21852,24 @@ void InterCodeProcedure::BuildTraces(bool expand, bool dominators, bool compact) mEntryBlock->BuildDominatorTree(nullptr); } +void InterCodeProcedure::TrimBlocks(void) +{ + int j = 1; + for (int i = 1; i < mBlocks.Size(); i++) + { + InterCodeBasicBlock* block = mBlocks[i]; + if (block->mNumEntries > 0) + { + block->mIndex = j; + mBlocks[j++] = block; + } + else + delete block; + } + mBlocks.SetSize(j, false); + mNumBlocks = j; +} + void InterCodeProcedure::BuildDataFlowSets(void) { int numTemps = mTemporaries.Size(); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 9a0830a..99643fb 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -690,6 +690,7 @@ protected: void ResetEntryBlocks(void); public: InterCodeBasicBlock * mEntryBlock; + int mNumBlocks; GrowingInterCodeBasicBlockPtrArray mBlocks; GrowingTypeArray mTemporaries; GrowingIntArray mTempOffset, mTempSizes; @@ -748,6 +749,7 @@ public: protected: void BuildLocalAliasTable(void); void BuildTraces(bool expand, bool dominators = true, bool compact = false); + void TrimBlocks(void); void EarlyBranchElimination(void); void BuildDataFlowSets(void); void RenameTemporaries(void); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 070c121..cd35a53 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1797,7 +1797,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I if (!ccdec->mLinkerObject) this->TranslateProcedure(proc->mModule, ccdec->mValue, ccdec); - bool canInline = (mCompilerOptions & COPT_OPTIMIZE_INLINE) && !(inlineMapper && inlineMapper->mDepth > 10); + bool canInline = ((mCompilerOptions & COPT_OPTIMIZE_INLINE) || (ccdec->mFlags & DTF_FORCE_INLINE)) && !(inlineMapper && inlineMapper->mDepth > 10); bool doInline = false; if (canInline) @@ -1812,6 +1812,9 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I } } + if ((ccdec->mFlags & DTF_FORCE_INLINE) && !doInline) + mErrors->Error(exp->mLocation, EWARN_FUNCTION_NOT_INLINED, "Function with __forceinline not inlined", ccdec->mQualIdent); + if (doInline) { DestructStack* destack = nullptr; @@ -3781,7 +3784,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* bool canInline = exp->mLeft->mType == EX_CONSTANT && exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION && - (mCompilerOptions & COPT_OPTIMIZE_INLINE) && + ((mCompilerOptions & COPT_OPTIMIZE_INLINE) || (exp->mLeft->mDecValue->mFlags & DTF_FORCE_INLINE)) && !(inlineMapper && inlineMapper->mDepth > 10) && exp->mType != EX_VCALL; bool doInline = false, inlineConstexpr = false; @@ -3831,8 +3834,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - Expression * funcexp = exp->mLeft; - + Expression* funcexp = exp->mLeft; + + if (funcexp->mType == EX_CONSTANT && (funcexp->mDecValue->mFlags & DTF_FORCE_INLINE)) + mErrors->Error(exp->mLocation, EWARN_FUNCTION_NOT_INLINED, "Function with __forceinline not inlined", funcexp->mDecValue->mQualIdent); + vl = TranslateExpression(procType, proc, block, funcexp, destack, gotos, breakBlock, continueBlock, inlineMapper); vl = Dereference(proc, exp, block, inlineMapper, vl); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 3a737b1..d35e84e 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -4699,6 +4699,11 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex storageFlags |= DTF_PREVENT_INLINE; mScanner->NextToken(); } + else if (mScanner->mToken == TK_FORCEINLINE) + { + storageFlags |= DTF_FORCE_INLINE | DTF_REQUEST_INLINE; + mScanner->NextToken(); + } else if (mScanner->mToken == TK_INLINE) { storageFlags |= DTF_REQUEST_INLINE; @@ -5341,7 +5346,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } } - pdec->mFlags |= ndec->mFlags & (DTF_REQUEST_INLINE | DTF_PREVENT_INLINE); + pdec->mFlags |= ndec->mFlags & (DTF_REQUEST_INLINE | DTF_PREVENT_INLINE | DTF_FORCE_INLINE); ndec = pdec; } @@ -5436,7 +5441,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } else if (pthis) { - ndec->mFlags |= storageFlags & (DTF_STATIC | DTF_PREVENT_INLINE); + ndec->mFlags |= storageFlags & (DTF_STATIC | DTF_PREVENT_INLINE | DTF_FORCE_INLINE); } ndec->mOffset = 0; @@ -11372,6 +11377,7 @@ void Parser::ParseTemplateDeclarationBody(Declaration * tdec, Declaration * pthi ConsumeTokenIf(TK_INLINE); ConsumeTokenIf(TK_NOINLINE); + ConsumeTokenIf(TK_FORCEINLINE); ConsumeTokenIf(TK_CONSTEXPR); Declaration* bdec = ParseBaseTypeDeclaration(0, true); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 6199ea7..f9c0166 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -60,6 +60,7 @@ const char* TokenNames[] = "__export", "__zeropage", "__noinline", + "__forceinline", "__striped", "__dynstack", @@ -1798,6 +1799,8 @@ void Scanner::NextRawToken(void) mToken = TK_ZEROPAGE; else if (!strcmp(tkident, "__noinline")) mToken = TK_NOINLINE; + else if (!strcmp(tkident, "__forceinline")) + mToken = TK_FORCEINLINE; else if (!strcmp(tkident, "__striped")) mToken = TK_STRIPED; else if (!strcmp(tkident, "__dynstack")) diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 3b616ba..faa8d80 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -58,6 +58,7 @@ enum Token TK_EXPORT, TK_ZEROPAGE, TK_NOINLINE, + TK_FORCEINLINE, TK_STRIPED, TK_DYNSTACK,