Add __forceinline storage specifier

This commit is contained in:
drmortalwombat 2024-10-02 18:27:20 +02:00
parent 6af50f5eae
commit f6c78d57ef
10 changed files with 56 additions and 12 deletions

View File

@ -6548,7 +6548,7 @@ void ByteCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedure
{ {
mID = proc->mID; mID = proc->mID;
mNumBlocks = proc->mBlocks.Size(); mNumBlocks = proc->mNumBlocks;
tblocks = new ByteCodeBasicBlock * [mNumBlocks]; tblocks = new ByteCodeBasicBlock * [mNumBlocks];
for (int i = 0; i < mNumBlocks; i++) for (int i = 0; i < mNumBlocks; i++)

View File

@ -104,6 +104,7 @@ static const uint64 DTF_CONSTEXPR = (1ULL << 31);
static const uint64 DTF_AUTO_TEMPLATE = (1ULL << 32); static const uint64 DTF_AUTO_TEMPLATE = (1ULL << 32);
static const uint64 DTF_BANK_INLAY = (1ULL << 33); static const uint64 DTF_BANK_INLAY = (1ULL << 33);
static const uint64 DTF_PURE_VIRTUAL = (1ULL << 34); 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_VARIABLE = (1ULL << 36);
static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 37); 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); static const uint64 DTF_FUNC_NO_RETURN = (1ULL << 51);
class Declaration; class Declaration;
enum ScopeLevel enum ScopeLevel

View File

@ -43,6 +43,7 @@ enum ErrorID
EWARN_INVALID_VALUE_RANGE, EWARN_INVALID_VALUE_RANGE,
EWARN_DEFAULT_COPY_DEPRECATED, EWARN_DEFAULT_COPY_DEPRECATED,
EWARN_INSUFFICIENT_MEMORY, EWARN_INSUFFICIENT_MEMORY,
EWARN_FUNCTION_NOT_INLINED,
EERR_GENERIC = 3000, EERR_GENERIC = 3000,
EERR_FILE_NOT_FOUND, EERR_FILE_NOT_FOUND,

View File

@ -161,7 +161,7 @@ int GlobalAnalyzer::CallerInvokes(Declaration* called)
int GlobalAnalyzer::CallerInvokes(Declaration* caller, Declaration* called) int GlobalAnalyzer::CallerInvokes(Declaration* caller, Declaration* called)
{ {
int n = 1; 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); n = CallerInvokes(caller);
return n > 1 ? n : 1; 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); // printf("CHECK INLINING %s (%d) %d * (%d - 1)\n", f->mIdent->mString, f->mComplexity, cost, invokes);
bool doinline = false; 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; doinline = true;
if (f->mLocalSize < 100) if (f->mLocalSize < 100)
{ {

View File

@ -5844,7 +5844,7 @@ InterCodeBasicBlock::InterCodeBasicBlock(InterCodeProcedure * proc)
mUnreachable = false; mUnreachable = false;
mValueRangeValid = false; mValueRangeValid = false;
mIndex = proc->mBlocks.Size(); mIndex = proc->mNumBlocks++;
proc->mBlocks.Push(this); proc->mBlocks.Push(this);
} }
@ -7441,6 +7441,8 @@ bool InterCodeBasicBlock::EarlyBranchElimination(const GrowingInstructionPtrArra
if (cins->mConst.mType == IT_BOOL) if (cins->mConst.mType == IT_BOOL)
{ {
mInstructions[sz - 1]->mCode = IC_JUMP; mInstructions[sz - 1]->mCode = IC_JUMP;
mInstructions[sz - 1]->mNumOperands = 0;
if (cins->mConst.mIntConst) if (cins->mConst.mIntConst)
mFalseJump->mNumEntries--; mFalseJump->mNumEntries--;
else else
@ -21668,7 +21670,7 @@ void InterCodeBasicBlock::WarnUnreachable(void)
InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & location, const Ident* ident, LinkerObject * linkerObject) 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), mRenameTable(-1), mRenameUnionTable(-1), mGlobalRenameTable(-1),
mValueForwardingTable(nullptr), mLocalVars(nullptr), mParamVars(nullptr), mModule(mod), mValueForwardingTable(nullptr), mLocalVars(nullptr), mParamVars(nullptr), mModule(mod),
mIdent(ident), mLinkerObject(linkerObject), mIdent(ident), mLinkerObject(linkerObject),
@ -21809,7 +21811,10 @@ void InterCodeProcedure::EarlyBranchElimination(void)
ResetVisited(); ResetVisited();
while (mEntryBlock->EarlyBranchElimination(ctemps)) while (mEntryBlock->EarlyBranchElimination(ctemps))
{} {
BuildTraces(true);
TrimBlocks();
}
} }
void InterCodeProcedure::BuildTraces(bool expand, bool dominators, bool compact) 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); 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) void InterCodeProcedure::BuildDataFlowSets(void)
{ {
int numTemps = mTemporaries.Size(); int numTemps = mTemporaries.Size();

View File

@ -690,6 +690,7 @@ protected:
void ResetEntryBlocks(void); void ResetEntryBlocks(void);
public: public:
InterCodeBasicBlock * mEntryBlock; InterCodeBasicBlock * mEntryBlock;
int mNumBlocks;
GrowingInterCodeBasicBlockPtrArray mBlocks; GrowingInterCodeBasicBlockPtrArray mBlocks;
GrowingTypeArray mTemporaries; GrowingTypeArray mTemporaries;
GrowingIntArray mTempOffset, mTempSizes; GrowingIntArray mTempOffset, mTempSizes;
@ -748,6 +749,7 @@ public:
protected: protected:
void BuildLocalAliasTable(void); void BuildLocalAliasTable(void);
void BuildTraces(bool expand, bool dominators = true, bool compact = false); void BuildTraces(bool expand, bool dominators = true, bool compact = false);
void TrimBlocks(void);
void EarlyBranchElimination(void); void EarlyBranchElimination(void);
void BuildDataFlowSets(void); void BuildDataFlowSets(void);
void RenameTemporaries(void); void RenameTemporaries(void);

View File

@ -1797,7 +1797,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I
if (!ccdec->mLinkerObject) if (!ccdec->mLinkerObject)
this->TranslateProcedure(proc->mModule, ccdec->mValue, ccdec); 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; bool doInline = false;
if (canInline) 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) if (doInline)
{ {
DestructStack* destack = nullptr; DestructStack* destack = nullptr;
@ -3781,7 +3784,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
bool canInline = exp->mLeft->mType == EX_CONSTANT && bool canInline = exp->mLeft->mType == EX_CONSTANT &&
exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION && 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) && !(inlineMapper && inlineMapper->mDepth > 10) &&
exp->mType != EX_VCALL; exp->mType != EX_VCALL;
bool doInline = false, inlineConstexpr = false; bool doInline = false, inlineConstexpr = false;
@ -3831,7 +3834,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
} }
else 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 = TranslateExpression(procType, proc, block, funcexp, destack, gotos, breakBlock, continueBlock, inlineMapper);

View File

@ -4699,6 +4699,11 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
storageFlags |= DTF_PREVENT_INLINE; storageFlags |= DTF_PREVENT_INLINE;
mScanner->NextToken(); mScanner->NextToken();
} }
else if (mScanner->mToken == TK_FORCEINLINE)
{
storageFlags |= DTF_FORCE_INLINE | DTF_REQUEST_INLINE;
mScanner->NextToken();
}
else if (mScanner->mToken == TK_INLINE) else if (mScanner->mToken == TK_INLINE)
{ {
storageFlags |= DTF_REQUEST_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; ndec = pdec;
} }
@ -5436,7 +5441,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
} }
else if (pthis) 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; ndec->mOffset = 0;
@ -11372,6 +11377,7 @@ void Parser::ParseTemplateDeclarationBody(Declaration * tdec, Declaration * pthi
ConsumeTokenIf(TK_INLINE); ConsumeTokenIf(TK_INLINE);
ConsumeTokenIf(TK_NOINLINE); ConsumeTokenIf(TK_NOINLINE);
ConsumeTokenIf(TK_FORCEINLINE);
ConsumeTokenIf(TK_CONSTEXPR); ConsumeTokenIf(TK_CONSTEXPR);
Declaration* bdec = ParseBaseTypeDeclaration(0, true); Declaration* bdec = ParseBaseTypeDeclaration(0, true);

View File

@ -60,6 +60,7 @@ const char* TokenNames[] =
"__export", "__export",
"__zeropage", "__zeropage",
"__noinline", "__noinline",
"__forceinline",
"__striped", "__striped",
"__dynstack", "__dynstack",
@ -1798,6 +1799,8 @@ void Scanner::NextRawToken(void)
mToken = TK_ZEROPAGE; mToken = TK_ZEROPAGE;
else if (!strcmp(tkident, "__noinline")) else if (!strcmp(tkident, "__noinline"))
mToken = TK_NOINLINE; mToken = TK_NOINLINE;
else if (!strcmp(tkident, "__forceinline"))
mToken = TK_FORCEINLINE;
else if (!strcmp(tkident, "__striped")) else if (!strcmp(tkident, "__striped"))
mToken = TK_STRIPED; mToken = TK_STRIPED;
else if (!strcmp(tkident, "__dynstack")) else if (!strcmp(tkident, "__dynstack"))

View File

@ -58,6 +58,7 @@ enum Token
TK_EXPORT, TK_EXPORT,
TK_ZEROPAGE, TK_ZEROPAGE,
TK_NOINLINE, TK_NOINLINE,
TK_FORCEINLINE,
TK_STRIPED, TK_STRIPED,
TK_DYNSTACK, TK_DYNSTACK,