Add warning for static buffer overflow

This commit is contained in:
drmortalwombat 2024-04-15 15:40:37 +02:00
parent 755c9234e1
commit 611f672b81
6 changed files with 185 additions and 111 deletions

View File

@ -40,6 +40,7 @@ enum ErrorID
EWARN_NUMERIC_0_USED_AS_NULLPTR, EWARN_NUMERIC_0_USED_AS_NULLPTR,
EWARN_FLOAT_TO_INT, EWARN_FLOAT_TO_INT,
EWARN_UNDEFINED_POINTER_ARITHMETIC, EWARN_UNDEFINED_POINTER_ARITHMETIC,
EWARN_INVALID_VALUE_RANGE,
EERR_GENERIC = 3000, EERR_GENERIC = 3000,
EERR_FILE_NOT_FOUND, EERR_FILE_NOT_FOUND,

View File

@ -118,6 +118,11 @@ void IntegerValueRange::LimitMaxWeak(int64 value)
} }
} }
bool IntegerValueRange::IsInvalid(void) const
{
return mMinState == S_BOUND && mMaxState == S_BOUND && mMinValue > mMaxValue;
}
bool IntegerValueRange::IsConstant(void) const bool IntegerValueRange::IsConstant(void) const
{ {
return mMinState == S_BOUND && mMaxState == S_BOUND && mMinValue == mMaxValue; return mMinState == S_BOUND && mMaxState == S_BOUND && mMinValue == mMaxValue;
@ -8077,6 +8082,12 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
vr.mMaxValue <<= ins->mSrc[0].mIntConst; vr.mMaxValue <<= ins->mSrc[0].mIntConst;
vr.mMinValue <<= ins->mSrc[0].mIntConst; vr.mMinValue <<= ins->mSrc[0].mIntConst;
if (ins->mDst.mType == IT_INT8 && vr.mMaxState == IntegerValueRange::S_BOUND && vr.mMaxValue > 255)
{
vr.mMinState = IntegerValueRange::S_UNBOUND;
vr.mMaxState = IntegerValueRange::S_UNBOUND;
}
} }
else if (ins->mSrc[0].IsUByte() && ins->mSrc[0].mRange.mMaxValue < 16) else if (ins->mSrc[0].IsUByte() && ins->mSrc[0].mRange.mMaxValue < 16)
{ {
@ -10519,7 +10530,7 @@ bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArra
nins->mSrc[0] = ains->mSrc[1]; nins->mSrc[0] = ains->mSrc[1];
nins->mDst.mTemp = spareTemps++; nins->mDst.mTemp = spareTemps++;
nins->mDst.mType = IT_INT16; nins->mDst.mType = IT_INT16;
nins->mDst.mRange = pins->mDst.mRange; nins->mDst.mRange = ains->mSrc[1].mRange;
mInstructions.Insert(i, nins); mInstructions.Insert(i, nins);
ins->mSrc[0] = nins->mDst; ins->mSrc[0] = nins->mDst;
@ -19140,6 +19151,31 @@ void InterCodeBasicBlock::CollectGlobalReferences(NumberSet& referencedGlobals,
} }
} }
void InterCodeBasicBlock::WarnInvalidValueRanges(void)
{
if (!mVisited)
{
mVisited = true;
for (int i = 0; i < mInstructions.Size(); i++)
{
InterInstruction* ins = mInstructions[i];
for (int j = 0; j < ins->mNumOperands; j++)
{
if (ins->mSrc[j].mTemp >= 0 && ins->mSrc[j].mRange.IsInvalid())
{
mProc->mModule->mErrors->Error(ins->mLocation, EWARN_INVALID_VALUE_RANGE, "Invalid value range");
}
}
}
if (mTrueJump) mTrueJump->WarnInvalidValueRanges();
if (mFalseJump) mFalseJump->WarnInvalidValueRanges();
}
}
void InterCodeBasicBlock::WarnUsedUndefinedVariables(void) void InterCodeBasicBlock::WarnUsedUndefinedVariables(void)
{ {
if (!mVisited) if (!mVisited)
@ -19883,6 +19919,16 @@ void InterCodeProcedure::WarnUsedUndefinedVariables(void)
mEntryBlock->WarnUsedUndefinedVariables(); mEntryBlock->WarnUsedUndefinedVariables();
} }
void InterCodeProcedure::WarnInvalidValueRanges(void)
{
ResetEntryBlocks();
ResetVisited();
mEntryBlock->CollectEntryBlocks(nullptr);
ResetVisited();
mEntryBlock->WarnInvalidValueRanges();
}
void InterCodeProcedure::TempForwarding(bool reverse, bool checkloops) void InterCodeProcedure::TempForwarding(bool reverse, bool checkloops)
{ {
@ -20503,7 +20549,7 @@ void InterCodeProcedure::Close(void)
{ {
GrowingTypeArray tstack(IT_NONE); GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "addGameObjectCannon"); CheckFunc = !strcmp(mIdent->mString, "opp::ostream::operator<<");
CheckCase = false; CheckCase = false;
mEntryBlock = mBlocks[0]; mEntryBlock = mBlocks[0];
@ -21409,6 +21455,8 @@ void InterCodeProcedure::Close(void)
BuildTraces(false, false, true); BuildTraces(false, false, true);
DisassembleDebug("Final Merged basic blocks"); DisassembleDebug("Final Merged basic blocks");
WarnInvalidValueRanges();
BuildDataFlowSets(); BuildDataFlowSets();
MapCallerSavedTemps(); MapCallerSavedTemps();

View File

@ -172,6 +172,7 @@ public:
void SetLimit(int64 minValue, int64 maxValue); void SetLimit(int64 minValue, int64 maxValue);
bool IsConstant(void) const; bool IsConstant(void) const;
bool IsInvalid(void) const;
void LimitMin(int64 value); void LimitMin(int64 value);
void LimitMax(int64 value); void LimitMax(int64 value);
@ -619,6 +620,7 @@ public:
bool SameExitCode(const InterCodeBasicBlock* block) const; bool SameExitCode(const InterCodeBasicBlock* block) const;
void WarnUsedUndefinedVariables(void); void WarnUsedUndefinedVariables(void);
void WarnInvalidValueRanges(void);
void CheckValueReturn(void); void CheckValueReturn(void);
void CheckNullptrDereference(void); void CheckNullptrDereference(void);
@ -732,6 +734,7 @@ protected:
void MergeBasicBlocks(void); void MergeBasicBlocks(void);
void CheckUsedDefinedTemps(void); void CheckUsedDefinedTemps(void);
void WarnUsedUndefinedVariables(void); void WarnUsedUndefinedVariables(void);
void WarnInvalidValueRanges(void);
void PropagateMemoryAliasingInfo(void); void PropagateMemoryAliasingInfo(void);
void MoveConditionsOutOfLoop(void); void MoveConditionsOutOfLoop(void);

View File

@ -9245,97 +9245,96 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
int sreg0 = ins->mSrc[sop0].mTemp < 0 ? -1 : BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop0].mTemp]; int sreg0 = ins->mSrc[sop0].mTemp < 0 ? -1 : BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop0].mTemp];
if (ins->mSrc[sop1].mTemp < 0) if (ins->mSrc[sop1].mTemp >= 0 && ins->mSrc[sop0].mTemp >= 0 && sins1 && sins1 == sins0)
{
union { float f; unsigned int v; } cc;
if (ins->mOperator == IA_SUB && flipop)
{
changedSign = true;
cc.f = float(-ins->mSrc[sop1].mFloatConst);
}
else
cc.f = float(ins->mSrc[sop1].mFloatConst);
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
}
else if (sins1)
{ {
LoadValueToReg(proc, sins1, BC_REG_ACCU, nullptr, nullptr); LoadValueToReg(proc, sins1, BC_REG_ACCU, nullptr, nullptr);
} NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("fsplitx")));
else if (CheckPredAccuStore(BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp])) mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER | NCIF_USE_ZP_32_X, BC_REG_ACCU));
{
if (ins->mSrc[sop1].mFinal)
{
// cull previous store from accu to temp using direcrt forwarding
mIns.SetSize(mIns.Size() - 8);
}
if (sreg0 == BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp])
sreg0 = BC_REG_ACCU;
} }
else else
{ {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp] + 0)); if (ins->mSrc[sop1].mTemp < 0)
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp] + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp] + 2));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp] + 3));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
}
if (ins->mSrc[sop0].mTemp < 0)
{
union { float f; unsigned int v; } cc;
if (ins->mOperator == IA_SUB && !flipop)
{ {
changedSign = true; union { float f; unsigned int v; } cc;
cc.f = float(-ins->mSrc[sop0].mFloatConst);
if (ins->mOperator == IA_SUB && flipop)
{
changedSign = true;
cc.f = float(-ins->mSrc[sop1].mFloatConst);
}
else
cc.f = float(ins->mSrc[sop1].mFloatConst);
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
}
else if (sins1)
{
LoadValueToReg(proc, sins1, BC_REG_ACCU, nullptr, nullptr);
}
else if (CheckPredAccuStore(BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp]))
{
if (ins->mSrc[sop1].mFinal)
{
// cull previous store from accu to temp using direcrt forwarding
mIns.SetSize(mIns.Size() - 8);
}
if (sreg0 == BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp])
sreg0 = BC_REG_ACCU;
} }
else else
cc.f = float(ins->mSrc[sop0].mFloatConst); {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp] + 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp] + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp] + 2));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[sop1].mTemp] + 3));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
}
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff)); if (ins->mSrc[sop0].mTemp < 0)
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0)); {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff)); union { float f; unsigned int v; } cc;
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 2));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("fsplitt"))); if (ins->mOperator == IA_SUB && !flipop)
mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER)); {
} changedSign = true;
else if (sins0) cc.f = float(-ins->mSrc[sop0].mFloatConst);
{ }
LoadValueToReg(proc, sins0, BC_REG_WORK, nullptr, nullptr); else
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("fsplitt"))); cc.f = float(ins->mSrc[sop0].mFloatConst);
mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER));
} mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
else mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
{ mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 8) & 0xff));
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("fsplitx"))); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER | NCIF_USE_ZP_32_X, sreg0)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 16) & 0xff));
#if 0 mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 2));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 0)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 1)); NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("fsplitt")));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 2)); mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 2)); }
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg0 + 3)); else if (sins0)
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 3)); {
#endif LoadValueToReg(proc, sins0, BC_REG_WORK, nullptr, nullptr);
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("fsplitt")));
mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER));
}
else
{
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("fsplitx")));
mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER | NCIF_USE_ZP_32_X, sreg0));
}
} }
@ -49481,25 +49480,42 @@ NativeCodeGenerator::Runtime& NativeCodeGenerator::ResolveRuntime(const Ident* i
return mRuntime[i]; return mRuntime[i];
} }
static inline bool isfparam(const NativeCodeInstruction & cins, const NativeCodeInstruction & ins)
{
if (cins.mFlags & NCIF_RUNTIME)
{
if (ins.mAddress >= BC_REG_WORK && ins.mAddress < BC_REG_WORK + 8)
return true;
if (ins.mAddress >= BC_REG_ACCU && ins.mAddress < BC_REG_ACCU + 4)
return true;
}
else
{
if (ins.mAddress >= BC_REG_FPARAMS && ins.mAddress < BC_REG_FPARAMS_END)
return true;
}
return false;
}
void NativeCodeGenerator::RegisterFunctionCall(NativeCodeBasicBlock* block, int at) void NativeCodeGenerator::RegisterFunctionCall(NativeCodeBasicBlock* block, int at)
{ {
LinkerObject* lo = block->mIns[at].mLinkerObject; LinkerObject* lo = block->mIns[at].mLinkerObject;
if (lo->mIdent && !(block->mIns[at].mFlags & NCIF_USE_ZP_32_X)) if (lo->mIdent)// && !(block->mIns[at].mFlags & NCIF_USE_ZP_32_X))
{ {
uint64 fpmask = 0; uint64 fpmask = 0;
int i = at; int i = at;
while (i >= 2 && while (i >= 2 &&
block->mIns[i - 1].mType == ASMIT_STA && block->mIns[i - 1].mMode == ASMIM_ZERO_PAGE && block->mIns[i - 1].mType == ASMIT_STA && block->mIns[i - 1].mMode == ASMIM_ZERO_PAGE &&
block->mIns[i - 1].mAddress >= BC_REG_FPARAMS && block->mIns[i - 1].mAddress < BC_REG_FPARAMS_END && isfparam(block->mIns[at], block->mIns[i - 1]) &&
block->mIns[i - 2].mType == ASMIT_LDA && (block->mIns[i - 2].mMode == ASMIM_IMMEDIATE || block->mIns[i - 2].mMode == ASMIM_IMMEDIATE_ADDRESS || block->mIns[i - 2].mMode == ASMIM_ZERO_PAGE || block->mIns[i - 2].mMode == ASMIM_ABSOLUTE)) block->mIns[i - 2].mType == ASMIT_LDA && (block->mIns[i - 2].mMode == ASMIM_IMMEDIATE || block->mIns[i - 2].mMode == ASMIM_IMMEDIATE_ADDRESS || block->mIns[i - 2].mMode == ASMIM_ZERO_PAGE || block->mIns[i - 2].mMode == ASMIM_ABSOLUTE))
{ {
if (block->mIns[i - 2].mMode == ASMIM_ZERO_PAGE && block->mIns[i - 2].mAddress >= BC_REG_FPARAMS && block->mIns[i - 2].mAddress < BC_REG_FPARAMS_END) if (block->mIns[i - 2].mMode == ASMIM_ZERO_PAGE && block->mIns[i - 2].mAddress >= BC_REG_FPARAMS && block->mIns[i - 2].mAddress < BC_REG_FPARAMS_END)
{ {
if (fpmask & (1ull << (block->mIns[i - 2].mAddress - BC_REG_FPARAMS))) if (fpmask & (1ull << (block->mIns[i - 2].mAddress - BC_REG_WORK)))
break; break;
} }
fpmask |= 1ull << (block->mIns[i - 1].mAddress - BC_REG_FPARAMS); fpmask |= 1ull << (block->mIns[i - 1].mAddress - BC_REG_WORK);
i -= 2; i -= 2;
} }
@ -49508,16 +49524,18 @@ void NativeCodeGenerator::RegisterFunctionCall(NativeCodeBasicBlock* block, int
{ {
FunctionCall* ncp = new FunctionCall(); FunctionCall* ncp = new FunctionCall();
ncp->mLinkerObject = lo; ncp->mLinkerObject = lo;
ncp->mOffset = block->mIns[at].mAddress;
ncp->mProxyObject = nullptr; ncp->mProxyObject = nullptr;
ncp->mCount = 1; ncp->mCount = 1;
while (i < at) while (i < at)
{ {
ncp->mIns[block->mIns[i + 1].mAddress - BC_REG_FPARAMS] = block->mIns[i]; ncp->mIns[block->mIns[i + 1].mAddress - BC_REG_WORK] = block->mIns[i];
i += 2; i += 2;
} }
FunctionCall* cp = mFunctionCalls; FunctionCall* cp = mFunctionCalls;
while (cp && cp->mLinkerObject != ncp->mLinkerObject) while (cp && (cp->mLinkerObject != ncp->mLinkerObject || cp->mOffset != ncp->mOffset))
cp = cp->mNext; cp = cp->mNext;
if (!cp) if (!cp)
{ {
@ -49556,15 +49574,15 @@ bool NativeCodeGenerator::MergeFunctionCall(NativeCodeBasicBlock* block, int at)
int i = at; int i = at;
while (i >= 2 && while (i >= 2 &&
block->mIns[i - 1].mType == ASMIT_STA && block->mIns[i - 1].mMode == ASMIM_ZERO_PAGE && block->mIns[i - 1].mType == ASMIT_STA && block->mIns[i - 1].mMode == ASMIM_ZERO_PAGE &&
block->mIns[i - 1].mAddress >= BC_REG_FPARAMS && block->mIns[i - 1].mAddress < BC_REG_FPARAMS_END && isfparam(block->mIns[at], block->mIns[i - 1]) &&
block->mIns[i - 2].mType == ASMIT_LDA && (block->mIns[i - 2].mMode == ASMIM_IMMEDIATE || block->mIns[i - 2].mMode == ASMIM_IMMEDIATE_ADDRESS || block->mIns[i - 2].mMode == ASMIM_ZERO_PAGE || block->mIns[i - 2].mMode == ASMIM_ABSOLUTE)) block->mIns[i - 2].mType == ASMIT_LDA && (block->mIns[i - 2].mMode == ASMIM_IMMEDIATE || block->mIns[i - 2].mMode == ASMIM_IMMEDIATE_ADDRESS || block->mIns[i - 2].mMode == ASMIM_ZERO_PAGE || block->mIns[i - 2].mMode == ASMIM_ABSOLUTE))
{ {
if (block->mIns[i - 2].mMode == ASMIM_ZERO_PAGE && block->mIns[i - 2].mAddress >= BC_REG_FPARAMS && block->mIns[i - 2].mAddress < BC_REG_FPARAMS_END) if (block->mIns[i - 2].mMode == ASMIM_ZERO_PAGE && block->mIns[i - 2].mAddress >= BC_REG_FPARAMS && block->mIns[i - 2].mAddress < BC_REG_FPARAMS_END)
{ {
if (fpmask & (1ull << (block->mIns[i - 2].mAddress - BC_REG_FPARAMS))) if (fpmask & (1ull << (block->mIns[i - 2].mAddress - BC_REG_WORK)))
break; break;
} }
fpmask |= 1ull << (block->mIns[i - 1].mAddress - BC_REG_FPARAMS); fpmask |= 1ull << (block->mIns[i - 1].mAddress - BC_REG_WORK);
i -= 2; i -= 2;
} }
@ -49573,15 +49591,16 @@ bool NativeCodeGenerator::MergeFunctionCall(NativeCodeBasicBlock* block, int at)
{ {
FunctionCall ncp; FunctionCall ncp;
ncp.mLinkerObject = lo; ncp.mLinkerObject = lo;
ncp.mOffset = block->mIns[at].mAddress;
int j = i; int j = i;
while (i < at) while (i < at)
{ {
ncp.mIns[block->mIns[i + 1].mAddress - BC_REG_FPARAMS] = block->mIns[i]; ncp.mIns[block->mIns[i + 1].mAddress - BC_REG_WORK] = block->mIns[i];
i += 2; i += 2;
} }
FunctionCall* cp = mFunctionCalls; FunctionCall* cp = mFunctionCalls;
while (cp && cp->mLinkerObject != ncp.mLinkerObject) while (cp && (cp->mLinkerObject != ncp.mLinkerObject || cp->mOffset != ncp.mOffset))
cp = cp->mNext; cp = cp->mNext;
if (cp) if (cp)
{ {
@ -49607,7 +49626,7 @@ bool NativeCodeGenerator::MergeFunctionCall(NativeCodeBasicBlock* block, int at)
{ {
while (j < at) while (j < at)
{ {
if (bcp->mIns[block->mIns[j + 1].mAddress - BC_REG_FPARAMS].mType != ASMIT_INV) if (bcp->mIns[block->mIns[j + 1].mAddress - BC_REG_WORK].mType != ASMIT_INV)
{ {
block->mIns[j + 0].mType = ASMIT_NOP; block->mIns[j + 0].mMode = ASMIM_IMPLIED; block->mIns[j + 0].mType = ASMIT_NOP; block->mIns[j + 0].mMode = ASMIM_IMPLIED;
block->mIns[j + 1].mType = ASMIT_NOP; block->mIns[j + 1].mMode = ASMIM_IMPLIED; block->mIns[j + 1].mType = ASMIT_NOP; block->mIns[j + 1].mMode = ASMIM_IMPLIED;
@ -49615,6 +49634,7 @@ bool NativeCodeGenerator::MergeFunctionCall(NativeCodeBasicBlock* block, int at)
j += 2; j += 2;
} }
block->mIns[j].mLinkerObject = bcp->mProxyObject; block->mIns[j].mLinkerObject = bcp->mProxyObject;
block->mIns[j].mAddress = 0;
return true; return true;
} }
} }
@ -49675,13 +49695,13 @@ void NativeCodeGenerator::BuildFunctionProxies(void)
ocalls.Remove(besti); ocalls.Remove(besti);
for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++) for (int i = BC_REG_WORK; i < BC_REG_ACCU + 4; i++)
{ {
if (fi->mIns[i - BC_REG_FPARAMS].mType != ASMIT_INV) if (fi->mIns[i - BC_REG_WORK].mType != ASMIT_INV)
{ {
if (!fi->mIns[i - BC_REG_FPARAMS].IsSame(fj->mIns[i - BC_REG_FPARAMS])) if (!fi->mIns[i - BC_REG_WORK].IsSame(fj->mIns[i - BC_REG_WORK]))
{ {
fi->mIns[i - BC_REG_FPARAMS].mType = ASMIT_INV; fi->mIns[i - BC_REG_WORK].mType = ASMIT_INV;
} }
} }
} }
@ -49709,9 +49729,9 @@ void NativeCodeGenerator::BuildFunctionProxies(void)
ncp->mProxyObject = mLinker->AddObject(ncp->mLinkerObject->mLocation, ncp->mLinkerObject->mIdent->Mangle("@proxy"), ncp->mLinkerObject->mSection, ncp->mLinkerObject->mType); ncp->mProxyObject = mLinker->AddObject(ncp->mLinkerObject->mLocation, ncp->mLinkerObject->mIdent->Mangle("@proxy"), ncp->mLinkerObject->mSection, ncp->mLinkerObject->mType);
ExpandingArray<uint8> code; ExpandingArray<uint8> code;
for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++) for (int i = BC_REG_WORK; i < BC_REG_ACCU + 4; i++)
{ {
NativeCodeInstruction& ins(ncp->mIns[i - BC_REG_FPARAMS]); NativeCodeInstruction& ins(ncp->mIns[i - BC_REG_WORK]);
if (ins.mType == ASMIT_LDA) if (ins.mType == ASMIT_LDA)
{ {
switch (ins.mMode) switch (ins.mMode)
@ -49792,7 +49812,7 @@ void NativeCodeGenerator::BuildFunctionProxies(void)
rl.mObject = ncp->mProxyObject; rl.mObject = ncp->mProxyObject;
rl.mOffset = code.Size(); rl.mOffset = code.Size();
rl.mRefObject = ncp->mLinkerObject; rl.mRefObject = ncp->mLinkerObject;
rl.mRefOffset = 0; rl.mRefOffset = ncp->mOffset;
rl.mFlags = LREF_LOWBYTE | LREF_HIGHBYTE; rl.mFlags = LREF_LOWBYTE | LREF_HIGHBYTE;
ncp->mProxyObject->AddReference(rl); ncp->mProxyObject->AddReference(rl);
code.Push(0); code.Push(0);
@ -49818,8 +49838,8 @@ void NativeCodeGenerator::RegisterRuntime(const Ident* ident, LinkerObject* obje
bool NativeCodeGenerator::FunctionCall::IsSame(const FunctionCall* fc) const bool NativeCodeGenerator::FunctionCall::IsSame(const FunctionCall* fc) const
{ {
for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++) for (int i = BC_REG_WORK; i < BC_REG_ACCU + 4; i++)
if (!mIns[i - BC_REG_FPARAMS].IsSame(fc->mIns[i - BC_REG_FPARAMS])) if (!mIns[i - BC_REG_WORK].IsSame(fc->mIns[i - BC_REG_WORK]))
return false; return false;
return true; return true;
} }
@ -49828,11 +49848,11 @@ int NativeCodeGenerator::FunctionCall::Matches(const FunctionCall* fc) const
{ {
int match = 0; int match = 0;
for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++) for (int i = BC_REG_WORK; i < BC_REG_ACCU + 4; i++)
{ {
if (fc->mIns[i - BC_REG_FPARAMS].mType != ASMIT_INV) if (fc->mIns[i - BC_REG_WORK].mType != ASMIT_INV)
{ {
if (!mIns[i - BC_REG_FPARAMS].IsSame(fc->mIns[i - BC_REG_FPARAMS])) if (!mIns[i - BC_REG_WORK].IsSame(fc->mIns[i - BC_REG_WORK]))
return -1; return -1;
match++; match++;
} }
@ -49845,11 +49865,11 @@ int NativeCodeGenerator::FunctionCall::PotentialMatches(const FunctionCall* fc)
{ {
int match = 0; int match = 0;
for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++) for (int i = BC_REG_WORK; i < BC_REG_ACCU + 4; i++)
{ {
if (fc->mIns[i - BC_REG_FPARAMS].mType != ASMIT_INV) if (fc->mIns[i - BC_REG_WORK].mType != ASMIT_INV)
{ {
if (mIns[i - BC_REG_FPARAMS].IsSame(fc->mIns[i - BC_REG_FPARAMS])) if (mIns[i - BC_REG_WORK].IsSame(fc->mIns[i - BC_REG_WORK]))
match++; match++;
} }
} }

View File

@ -840,7 +840,7 @@ public:
LinkerObject * mLinkerObject, * mProxyObject; LinkerObject * mLinkerObject, * mProxyObject;
NativeCodeInstruction mIns[64]; NativeCodeInstruction mIns[64];
FunctionCall * mNext, * mSame; FunctionCall * mNext, * mSame;
int mCount; int mCount, mOffset;
bool IsSame(const FunctionCall* fc) const; bool IsSame(const FunctionCall* fc) const;
int Matches(const FunctionCall* fc) const; int Matches(const FunctionCall* fc) const;

View File

@ -212,6 +212,8 @@ int main2(int argc, const char** argv)
compiler->mCompilerOptions |= COPT_OPTIMIZE_CONST_PARAMS; compiler->mCompilerOptions |= COPT_OPTIMIZE_CONST_PARAMS;
else if (arg[2] == 'g') else if (arg[2] == 'g')
compiler->mCompilerOptions |= COPT_OPTIMIZE_GLOBAL; compiler->mCompilerOptions |= COPT_OPTIMIZE_GLOBAL;
else if (arg[2] == 'm')
compiler->mCompilerOptions |= COPT_OPTIMIZE_MERGE_CALLS;
} }
else if (arg[1] == 'e') else if (arg[1] == 'e')
{ {