Static call graph analysis for function arguments

This commit is contained in:
drmortalwombat 2023-01-15 18:38:18 +01:00
parent 761206d009
commit 02db5b5eb1
16 changed files with 472 additions and 205 deletions

View File

@ -83,6 +83,7 @@ The compiler is command line driven, and creates an executable .prg file.
* -d64 : create a d64 disk image
* -f : add a binary file to the disk image
* -fz : add a compressed binary file to the disk image
* -xz : extended zero page usage, more zero page space, but no return to basic
A list of source files can be provided.

View File

@ -49,6 +49,22 @@ void Compiler::AddDefine(const Ident* ident, const char* value)
bool Compiler::ParseSource(void)
{
if (mCompilerOptions & COPT_EXTENDED_ZERO_PAGE)
{
BC_REG_FPARAMS = 0x0d;
BC_REG_FPARAMS_END = 0x25;
BC_REG_IP = 0x25;
BC_REG_ACCU = 0x27;
BC_REG_ADDR = 0x2b;
BC_REG_STACK = 0x2f;
BC_REG_LOCALS = 0x31;
#if 1
BC_REG_TMP = 0x33;
BC_REG_TMP_SAVED = 0x53;
#endif
}
mPreprocessor->mCompilerOptions = mCompilerOptions;
mLinker->mCompilerOptions = mCompilerOptions;
@ -220,6 +236,8 @@ bool Compiler::GenerateCode(void)
regionMain->mSections.Push(mCompilationUnits->mSectionStack);
}
mInterCodeModule->InitParamStack(mCompilationUnits->mSectionStack);
dcrtstart->mSection = sectionStartup;
mGlobalAnalyzer->mCompilerOptions = mCompilerOptions;

View File

@ -12,6 +12,8 @@ static const uint64 COPT_OPTIMIZE_CONST_EXPRESSIONS = 0x00000080;
static const uint64 COPT_OPTIMIZE_CODE_SIZE = 0x00000100;
static const uint64 COPT_EXTENDED_ZERO_PAGE = 0x00010000;
static const uint64 COPT_TARGET_PRG = 0x100000000ULL;
static const uint64 COPT_TARGET_CRT16 = 0x200000000ULL;
static const uint64 COPT_TARGET_CRT512 = 0x400000000ULL;

View File

@ -797,7 +797,7 @@ const char* NativeCodeDisassembler::TempName(uint8 tmp, char* buffer, InterCodeP
sprintf_s(buffer, 10, "P%d", tmp - BC_REG_FPARAMS);
return buffer;
}
else if (tmp >= BC_REG_LOCALS && tmp <= BC_REG_LOCALS + 3)
else if (tmp >= BC_REG_LOCALS && tmp <= BC_REG_LOCALS + 1)
{
sprintf_s(buffer, 10, "FP + %d", tmp - BC_REG_LOCALS);
return buffer;

View File

@ -156,25 +156,52 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec)
nbase = 1000;
}
int nparams = 0;
int nparams = 0, npalign = 0;
int numfpzero = BC_REG_FPARAMS_END - BC_REG_FPARAMS;
int fplimit = numfpzero;
if (!(procDec->mFlags & DTF_FUNC_INTRCALLED))
fplimit += 256;
if (procDec->mBase->mBase->mType == DT_TYPE_STRUCT)
{
if (nbase < numfpzero && nbase + 2 > numfpzero)
nbase = numfpzero;
nparams += 2;
}
Declaration* dec = procDec->mBase->mParams;
while (dec)
{
// Check for paramter crossing boundary
if (nbase + nparams < numfpzero && nbase + nparams + dec->mBase->mSize > numfpzero)
{
npalign = numfpzero - (nbase + nparams);
nparams += npalign;
}
nparams += dec->mBase->mSize;
dec = dec->mNext;
}
if (nbase + nparams <= BC_REG_FPARAMS_END - BC_REG_FPARAMS)
if (nbase + nparams <= fplimit)
{
procDec->mFastCallBase = nbase;
procDec->mFastCallSize = nparams;
procDec->mBase->mFastCallBase = nbase;
procDec->mBase->mFastCallSize = nparams;
// Align fast call parameters to avoid crossing the zero page boundary
if (npalign)
{
Declaration* dec = procDec->mBase->mParams;
while (dec)
{
if (nbase + dec->mVarIndex + dec->mBase->mSize > numfpzero)
dec->mVarIndex += npalign;
dec = dec->mNext;
}
}
procDec->mBase->mFlags |= DTF_FASTCALL;
#if 0
printf("FASTCALL %s\n", f->mIdent->mString);
@ -410,16 +437,39 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec)
return exp->mDecValue->mBase;
case EX_CALL:
ldec = Analyze(exp->mLeft, procDec);
RegisterCall(procDec, ldec);
if (!(GetProcFlags(ldec) & (DTF_FUNC_INTRSAVE | DTF_INTERRUPT)))
if ((ldec->mFlags & DTF_INTRINSIC) && !ldec->mValue)
{
procDec->mFlags &= ~DTF_FUNC_INTRSAVE;
if (procDec->mFlags & DTF_INTERRUPT)
mErrors->Error(exp->mLocation, EWARN_NOT_INTERRUPT_SAFE, "Calling non interrupt safe function", ldec->mIdent);
}
else
{
RegisterCall(procDec, ldec);
if (!(GetProcFlags(ldec) & (DTF_FUNC_INTRSAVE | DTF_INTERRUPT)))
{
procDec->mFlags &= ~DTF_FUNC_INTRSAVE;
if (procDec->mFlags & DTF_INTERRUPT)
mErrors->Error(exp->mLocation, EWARN_NOT_INTERRUPT_SAFE, "Calling non interrupt safe function", ldec->mIdent);
}
}
if (exp->mRight)
{
// Check for struct to struct forwarding
Expression* rex = exp->mRight;
while (rex)
{
Expression* pex = rex->mType == EX_LIST ? rex->mLeft : rex;
if (pex->mType == EX_CALL && pex->mDecType->mType == DT_TYPE_STRUCT)
ldec->mBase->mFlags |= DTF_STACKCALL;
if (rex->mType == EX_LIST)
rex = rex->mRight;
else
rex = nullptr;
}
RegisterProc(Analyze(exp->mRight, procDec));
}
break;
case EX_LIST:
RegisterProc(Analyze(exp->mLeft, procDec));

View File

@ -85,7 +85,7 @@ void IntegerValueRange::LimitMaxBound(int64 value)
void IntegerValueRange::LimitMinWeak(int64 value)
{
if (mMinState == S_UNBOUND || mMinValue < value)
if (mMinState == S_UNBOUND || mMinState != S_UNKNOWN && mMinValue < value)
{
mMinState = S_BOUND;
mMinValue = value;
@ -95,7 +95,7 @@ void IntegerValueRange::LimitMinWeak(int64 value)
void IntegerValueRange::LimitMaxWeak(int64 value)
{
if (mMaxState == S_UNBOUND || mMaxValue > value)
if (mMaxState == S_UNBOUND || mMinState != S_UNKNOWN && mMaxValue > value)
{
mMaxState = S_BOUND;
mMaxValue = value;
@ -6130,6 +6130,7 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
default:
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
}
#if 1
if (ins->mDst.mType == IT_INT8)
{
@ -6600,6 +6601,11 @@ void InterCodeBasicBlock::RestartLocalIntegerRangeSets(int num, const GrowingVar
mMemoryValueSize.SetSize(num, false);
mEntryMemoryValueSize.SetSize(num, false);
mEntryParamValueRange.SetSize(paramVars.Size(), false);
mTrueParamValueRange.SetSize(paramVars.Size(), false);
mFalseParamValueRange.SetSize(paramVars.Size(), false);
mLocalParamValueRange.SetSize(paramVars.Size(), false);
for (int i = 0; i < mEntryValueRange.Size(); i++)
{
IntegerValueRange& vr(mEntryValueRange[i]);
@ -10080,7 +10086,7 @@ void ApplyStaticStack(InterOperand & iop, const GrowingVariableArray& localVars)
iop.mMemory = IM_GLOBAL;
iop.mLinkerObject = localVars[iop.mVarIndex]->mLinkerObject;
iop.mVarIndex = localVars[iop.mVarIndex]->mIndex;
}
}
}
void InterCodeBasicBlock::CollectStaticStack(LinkerObject* lobj, const GrowingVariableArray& localVars)
@ -10095,7 +10101,7 @@ void InterCodeBasicBlock::CollectStaticStack(LinkerObject* lobj, const GrowingVa
lobj->mStackSection->mSections.Push(mInstructions[i]->mSrc[0].mLinkerObject->mStackSection);
if (mInstructions[i]->mCode == IC_LOAD)
ApplyStaticStack(mInstructions[i]->mSrc[0], localVars);
ApplyStaticStack(mInstructions[i]->mSrc[0],localVars);
else if (mInstructions[i]->mCode == IC_STORE || mInstructions[i]->mCode == IC_LEA)
ApplyStaticStack(mInstructions[i]->mSrc[1], localVars);
else if (mInstructions[i]->mCode == IC_CONSTANT && mInstructions[i]->mDst.mType == IT_POINTER)
@ -10112,6 +10118,47 @@ void InterCodeBasicBlock::CollectStaticStack(LinkerObject* lobj, const GrowingVa
}
}
void PromoteStaticStackParam(InterOperand& iop, LinkerObject* paramlobj)
{
if (iop.mMemory == IM_FFRAME || iop.mMemory == IM_FPARAM)
{
if (iop.mVarIndex >= BC_REG_FPARAMS_END - BC_REG_FPARAMS)
{
int offset = iop.mVarIndex - (BC_REG_FPARAMS_END - BC_REG_FPARAMS);
iop.mMemory = IM_GLOBAL;
iop.mIntConst += offset;
iop.mLinkerObject = paramlobj;
paramlobj->EnsureSpace(iop.mIntConst, iop.mOperandSize);
}
}
}
void InterCodeBasicBlock::PromoteStaticStackParams(LinkerObject* paramlobj)
{
if (!mVisited)
{
mVisited = true;
for (int i = 0; i < mInstructions.Size(); i++)
{
if (mInstructions[i]->mCode == IC_LOAD)
PromoteStaticStackParam(mInstructions[i]->mSrc[0], paramlobj);
else if (mInstructions[i]->mCode == IC_STORE || mInstructions[i]->mCode == IC_LEA)
PromoteStaticStackParam(mInstructions[i]->mSrc[1], paramlobj);
else if (mInstructions[i]->mCode == IC_CONSTANT && mInstructions[i]->mDst.mType == IT_POINTER)
PromoteStaticStackParam(mInstructions[i]->mConst, paramlobj);
else if (mInstructions[i]->mCode == IC_COPY)
{
PromoteStaticStackParam(mInstructions[i]->mSrc[0], paramlobj);
PromoteStaticStackParam(mInstructions[i]->mSrc[1], paramlobj);
}
}
if (mTrueJump) mTrueJump->PromoteStaticStackParams(paramlobj);
if (mFalseJump) mFalseJump->PromoteStaticStackParams(paramlobj);
}
}
bool InterCodeBasicBlock::DropUnreachable(void)
{
if (!mVisited)
@ -14333,6 +14380,7 @@ void InterCodeProcedure::Close(void)
{
mLinkerObject->mFlags |= LOBJF_STATIC_STACK;
mLinkerObject->mStackSection = mModule->mLinker->AddSection(mIdent->Mangle("@stack"), LST_STATIC_STACK);
mLinkerObject->mStackSection->mSections.Push(mModule->mParamLinkerSection);
for (int i = 0; i < mLocalVars.Size(); i++)
{
@ -14458,14 +14506,17 @@ void InterCodeProcedure::Close(void)
MapCallerSavedTemps();
ResetVisited();
mEntryBlock->PromoteStaticStackParams(mModule->mParamLinkerObject);
if (mValueReturn)
{
ResetVisited();
mEntryBlock->CheckValueReturn(this);
}
if (mSaveTempsLinkerObject && mTempSize > 16)
mSaveTempsLinkerObject->AddSpace(mTempSize - 16);
if (mSaveTempsLinkerObject && mTempSize > BC_REG_TMP_SAVED - BC_REG_TMP)
mSaveTempsLinkerObject->AddSpace(mTempSize - (BC_REG_TMP_SAVED - BC_REG_TMP));
}
void InterCodeProcedure::AddCalledFunction(InterCodeProcedure* proc)
@ -14867,10 +14918,10 @@ void InterCodeProcedure::MapCallerSavedTemps(void)
ResetVisited();
mEntryBlock->BuildCallerSaveTempSet(callerSaved);
int callerSavedTemps = 0, calleeSavedTemps = 16, freeCallerSavedTemps = 0, freeTemps = 0;
int callerSavedTemps = 0, calleeSavedTemps = BC_REG_TMP_SAVED - BC_REG_TMP, freeCallerSavedTemps = 0, freeTemps = 0;
if (mCallsFunctionPointer)
freeCallerSavedTemps = 16;
freeCallerSavedTemps = BC_REG_TMP_SAVED - BC_REG_TMP;
else
{
for (int i = 0; i < mCalledFunctions.Size(); i++)
@ -14939,8 +14990,8 @@ void InterCodeProcedure::MapCallerSavedTemps(void)
printf("T%02d : %d, %d\n", i, mTempOffset[i], mTempSizes[i]);
#endif
if (mSaveTempsLinkerObject && mTempSize > 16)
mSaveTempsLinkerObject->AddSpace(mTempSize - 16);
if (mSaveTempsLinkerObject && mTempSize > BC_REG_TMP_SAVED - BC_REG_TMP)
mSaveTempsLinkerObject->AddSpace(mTempSize - (BC_REG_TMP_SAVED - BC_REG_TMP));
// printf("Map %s, %d, %d, %d, %d\n", mIdent->mString, freeTemps, callerSavedTemps, calleeSavedTemps, freeCallerSavedTemps);
}
@ -15004,7 +15055,7 @@ void InterCodeProcedure::Disassemble(const char* name, bool dumpSets)
}
InterCodeModule::InterCodeModule(Errors* errors, Linker * linker)
: mErrors(errors), mLinker(linker), mGlobalVars(nullptr), mProcedures(nullptr), mCompilerOptions(0)
: mErrors(errors), mLinker(linker), mGlobalVars(nullptr), mProcedures(nullptr), mCompilerOptions(0), mParamLinkerObject(nullptr), mParamLinkerSection(nullptr)
{
}
@ -15013,6 +15064,15 @@ InterCodeModule::~InterCodeModule(void)
}
void InterCodeModule::InitParamStack(LinkerSection* stackSection)
{
mParamLinkerSection = mLinker->AddSection(Ident::Unique("sstack"), LST_STATIC_STACK);
stackSection->mSections.Push(mParamLinkerSection);
mParamLinkerObject = mLinker->AddObject(Location(), Ident::Unique("sstack"), mParamLinkerSection, LOT_STACK);
}
bool InterCodeModule::Disassemble(const char* filename)
{
FILE* file;

View File

@ -518,6 +518,7 @@ public:
bool CheckStaticStack(void);
void CollectStaticStack(LinkerObject * lobj, const GrowingVariableArray& localVars);
void PromoteStaticStackParams(LinkerObject* paramlobj);
bool SameExitCode(const InterCodeBasicBlock* block) const;
@ -622,11 +623,15 @@ public:
InterCodeModule(Errors* errors, Linker * linker);
~InterCodeModule(void);
void InitParamStack(LinkerSection * stackSection);
bool Disassemble(const char* name);
GrowingInterCodeProcedurePtrArray mProcedures;
GrowingVariableArray mGlobalVars;
LinkerObject * mParamLinkerObject;
LinkerSection * mParamLinkerSection;
Linker * mLinker;
Errors* mErrors;

View File

@ -704,6 +704,186 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e
}
}
InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr)
{
Declaration* dec;
ExValue vl, vr;
Declaration* fdec = exp->mLeft->mDecValue;
Expression* fexp = fdec->mValue;
Declaration* ftype = fdec->mBase;
InlineMapper nmapper;
nmapper.mReturn = new InterCodeBasicBlock();
nmapper.mVarIndex = proc->mNumLocals;
nmapper.mConstExpr = inlineConstexpr;
proc->mNumLocals += fdec->mNumVars;
if (inlineMapper)
nmapper.mDepth = inlineMapper->mDepth + 1;
proc->Append(nmapper.mReturn);
Declaration* pdec = ftype->mParams;
Expression* pex = exp->mRight;
while (pex)
{
int nindex = proc->mNumLocals++;
Declaration* vdec = new Declaration(pex->mLocation, DT_VARIABLE);
InterInstruction* ains = new InterInstruction(pex->mLocation, IC_CONSTANT);
ains->mDst.mType = IT_POINTER;
ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType);
ains->mConst.mMemory = IM_LOCAL;
ains->mConst.mVarIndex = nindex;
if (pdec)
{
nmapper.mParams[pdec->mVarIndex] = nindex;
vdec->mVarIndex = nindex;
vdec->mBase = pdec->mBase;
if (pdec->mBase->mType == DT_TYPE_ARRAY)
ains->mConst.mOperandSize = 2;
else
ains->mConst.mOperandSize = pdec->mSize;
vdec->mSize = ains->mConst.mOperandSize;
vdec->mIdent = pdec->mIdent;
}
else
{
mErrors->Error(pex->mLocation, EERR_WRONG_PARAMETER, "Too many arguments for function call");
}
block->Append(ains);
Expression* texp;
if (pex->mType == EX_LIST)
{
texp = pex->mLeft;
pex = pex->mRight;
}
else
{
texp = pex;
pex = nullptr;
}
ExValue vp(pdec ? pdec->mBase : TheSignedIntTypeDeclaration, ains->mDst.mTemp, 1);
vr = TranslateExpression(procType, proc, block, texp, breakBlock, continueBlock, inlineMapper, &vp);
if (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)
{
if (pdec && !pdec->mBase->CanAssign(vr.mType))
mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types");
vr = Dereference(proc, texp, block, vr, 1);
if (vr.mReference != 1)
mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not an adressable expression");
if (vp.mTemp != vr.mTemp)
{
InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY);
cins->mSrc[0].mType = IT_POINTER;
cins->mSrc[0].mTemp = vr.mTemp;
cins->mSrc[0].mMemory = IM_INDIRECT;
cins->mSrc[0].mOperandSize = vr.mType->mSize;
cins->mSrc[0].mStride = vr.mType->mStripe;
cins->mSrc[1].mType = IT_POINTER;
cins->mSrc[1].mTemp = ains->mDst.mTemp;
cins->mSrc[1].mMemory = IM_INDIRECT;
cins->mSrc[1].mOperandSize = vr.mType->mSize;
cins->mConst.mOperandSize = vr.mType->mSize;
block->Append(cins);
}
}
else
{
if (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION)
vr = Dereference(proc, texp, block, vr, 1);
else
vr = Dereference(proc, texp, block, vr);
if (pdec)
{
if (!pdec->mBase->CanAssign(vr.mType))
mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types");
vr = CoerceType(proc, texp, block, vr, pdec->mBase);
}
else if (vr.mType->IsIntegerType() && vr.mType->mSize < 2)
{
vr = CoerceType(proc, texp, block, vr, TheSignedIntTypeDeclaration);
}
InterInstruction* wins = new InterInstruction(texp->mLocation, IC_STORE);
wins->mSrc[1].mMemory = IM_INDIRECT;
wins->mSrc[0].mType = InterTypeOf(vr.mType);;
wins->mSrc[0].mTemp = vr.mTemp;
wins->mSrc[1].mType = IT_POINTER;
wins->mSrc[1].mTemp = ains->mDst.mTemp;
if (pdec)
{
if (pdec->mBase->mType == DT_TYPE_ARRAY)
wins->mSrc[1].mOperandSize = 2;
else
wins->mSrc[1].mOperandSize = pdec->mSize;
}
else if (vr.mType->mSize > 2 && vr.mType->mType != DT_TYPE_ARRAY)
wins->mSrc[1].mOperandSize = vr.mType->mSize;
else
wins->mSrc[1].mOperandSize = 2;
block->Append(wins);
}
if (pdec)
pdec = pdec->mNext;
}
if (pdec)
mErrors->Error(exp->mLocation, EERR_WRONG_PARAMETER, "Not enough arguments for function call");
Declaration* rdec = nullptr;
if (ftype->mBase->mType != DT_TYPE_VOID)
{
int nindex = proc->mNumLocals++;
nmapper.mResult = nindex;
rdec = new Declaration(ftype->mLocation, DT_VARIABLE);
rdec->mVarIndex = nindex;
rdec->mBase = ftype->mBase;
rdec->mSize = rdec->mBase->mSize;
}
vl = TranslateExpression(ftype, proc, block, fexp, nullptr, nullptr, &nmapper);
InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP);
block->Append(jins);
block->Close(nmapper.mReturn, nullptr);
block = nmapper.mReturn;
if (rdec)
{
InterInstruction* ins = new InterInstruction(exp->mLocation, IC_CONSTANT);
ins->mDst.mType = IT_POINTER;
ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType);
ins->mConst.mOperandSize = rdec->mSize;
ins->mConst.mIntConst = rdec->mOffset;
ins->mConst.mVarIndex = rdec->mVarIndex;
ins->mConst.mMemory = IM_LOCAL;
block->Append(ins);
return ExValue(rdec->mBase, ins->mDst.mTemp, 1);
}
else
return ExValue(TheVoidTypeDeclaration);
}
InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper* inlineMapper, ExValue* lrexp)
{
Declaration* dec;
@ -2048,179 +2228,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
if (doInline)
{
Declaration* fdec = exp->mLeft->mDecValue;
Expression* fexp = fdec->mValue;
Declaration* ftype = fdec->mBase;
InlineMapper nmapper;
nmapper.mReturn = new InterCodeBasicBlock();
nmapper.mVarIndex = proc->mNumLocals;
nmapper.mConstExpr = inlineConstexpr;
proc->mNumLocals += fdec->mNumVars;
if (inlineMapper)
nmapper.mDepth = inlineMapper->mDepth + 1;
proc->Append(nmapper.mReturn);
Declaration* pdec = ftype->mParams;
Expression* pex = exp->mRight;
while (pex)
{
int nindex = proc->mNumLocals++;
Declaration* vdec = new Declaration(pex->mLocation, DT_VARIABLE);
InterInstruction* ains = new InterInstruction(pex->mLocation, IC_CONSTANT);
ains->mDst.mType = IT_POINTER;
ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType);
ains->mConst.mMemory = IM_LOCAL;
ains->mConst.mVarIndex = nindex;
if (pdec)
{
nmapper.mParams[pdec->mVarIndex] = nindex;
vdec->mVarIndex = nindex;
vdec->mBase = pdec->mBase;
if (pdec->mBase->mType == DT_TYPE_ARRAY)
ains->mConst.mOperandSize = 2;
else
ains->mConst.mOperandSize = pdec->mSize;
vdec->mSize = ains->mConst.mOperandSize;
vdec->mIdent = pdec->mIdent;
}
else
{
mErrors->Error(pex->mLocation, EERR_WRONG_PARAMETER, "Too many arguments for function call");
}
block->Append(ains);
Expression* texp;
if (pex->mType == EX_LIST)
{
texp = pex->mLeft;
pex = pex->mRight;
}
else
{
texp = pex;
pex = nullptr;
}
ExValue vp(pdec ? pdec->mBase : TheSignedIntTypeDeclaration, ains->mDst.mTemp, 1);
vr = TranslateExpression(procType, proc, block, texp, breakBlock, continueBlock, inlineMapper, &vp);
if (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)
{
if (pdec && !pdec->mBase->CanAssign(vr.mType))
mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types");
vr = Dereference(proc, texp, block, vr, 1);
if (vr.mReference != 1)
mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not an adressable expression");
if (vp.mTemp != vr.mTemp)
{
InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY);
cins->mSrc[0].mType = IT_POINTER;
cins->mSrc[0].mTemp = vr.mTemp;
cins->mSrc[0].mMemory = IM_INDIRECT;
cins->mSrc[0].mOperandSize = vr.mType->mSize;
cins->mSrc[0].mStride = vr.mType->mStripe;
cins->mSrc[1].mType = IT_POINTER;
cins->mSrc[1].mTemp = ains->mDst.mTemp;
cins->mSrc[1].mMemory = IM_INDIRECT;
cins->mSrc[1].mOperandSize = vr.mType->mSize;
cins->mConst.mOperandSize = vr.mType->mSize;
block->Append(cins);
}
}
else
{
if (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION)
vr = Dereference(proc, texp, block, vr, 1);
else
vr = Dereference(proc, texp, block, vr);
if (pdec)
{
if (!pdec->mBase->CanAssign(vr.mType))
mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types");
vr = CoerceType(proc, texp, block, vr, pdec->mBase);
}
else if (vr.mType->IsIntegerType() && vr.mType->mSize < 2)
{
vr = CoerceType(proc, texp, block, vr, TheSignedIntTypeDeclaration);
}
InterInstruction* wins = new InterInstruction(texp->mLocation, IC_STORE);
wins->mSrc[1].mMemory = IM_INDIRECT;
wins->mSrc[0].mType = InterTypeOf(vr.mType);;
wins->mSrc[0].mTemp = vr.mTemp;
wins->mSrc[1].mType = IT_POINTER;
wins->mSrc[1].mTemp = ains->mDst.mTemp;
if (pdec)
{
if (pdec->mBase->mType == DT_TYPE_ARRAY)
wins->mSrc[1].mOperandSize = 2;
else
wins->mSrc[1].mOperandSize = pdec->mSize;
}
else if (vr.mType->mSize > 2 && vr.mType->mType != DT_TYPE_ARRAY)
wins->mSrc[1].mOperandSize = vr.mType->mSize;
else
wins->mSrc[1].mOperandSize = 2;
block->Append(wins);
}
if (pdec)
pdec = pdec->mNext;
}
if (pdec)
mErrors->Error(exp->mLocation, EERR_WRONG_PARAMETER, "Not enough arguments for function call");
Declaration* rdec = nullptr;
if (ftype->mBase->mType != DT_TYPE_VOID)
{
int nindex = proc->mNumLocals++;
nmapper.mResult = nindex;
rdec = new Declaration(ftype->mLocation, DT_VARIABLE);
rdec->mVarIndex = nindex;
rdec->mBase = ftype->mBase;
rdec->mSize = rdec->mBase->mSize;
}
vl = TranslateExpression(ftype, proc, block, fexp, nullptr, nullptr, &nmapper);
InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP);
block->Append(jins);
block->Close(nmapper.mReturn, nullptr);
block = nmapper.mReturn;
if (rdec)
{
InterInstruction* ins = new InterInstruction(exp->mLocation, IC_CONSTANT);
ins->mDst.mType = IT_POINTER;
ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType);
ins->mConst.mOperandSize = rdec->mSize;
ins->mConst.mIntConst = rdec->mOffset;
ins->mConst.mVarIndex = rdec->mVarIndex;
ins->mConst.mMemory = IM_LOCAL;
block->Append(ins);
return ExValue(rdec->mBase, ins->mDst.mTemp, 1);
}
else
return ExValue(TheVoidTypeDeclaration);
return TranslateInline(procType, proc, block, exp, breakBlock, continueBlock, inlineMapper, inlineConstexpr);
}
else
{

View File

@ -58,6 +58,7 @@ protected:
ExValue CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, Declaration * type);
ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper * inlineMapper, ExValue * lrexp = nullptr);
void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, InlineMapper* inlineMapper);
ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr);
void BuildInitializer(InterCodeModule* mod, uint8 * dp, int offset, Declaration* data, InterVariable * variable);
};

View File

@ -71,6 +71,12 @@ void LinkerObject::AddData(const uint8* data, int size)
memcpy(mData, data, size);
}
void LinkerObject::EnsureSpace(int offset, int size)
{
if (offset + size > mSize)
AddSpace(offset + size);
}
uint8* LinkerObject::AddSpace(int size)
{
if (mSize != size)

View File

@ -174,6 +174,7 @@ public:
void AddData(const uint8* data, int size);
uint8* AddSpace(int size);
void EnsureSpace(int offset, int size);
GrowingArray<LinkerReference*> mReferences;

View File

@ -13750,6 +13750,83 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
for (int i = 0; i < mIns.Size(); i++)
{
#if 1
if (i + 6 < mIns.Size())
{
if (mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 1].mType == ASMIT_ASL && mIns[i + 1].mMode == ASMIM_IMPLIED &&
mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0x00 &&
mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress == 0xff &&
mIns[i + 4].mType == ASMIT_EOR && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0xff &&
mIns[i + 5].mType == ASMIT_ASL && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 0].mAddress &&
mIns[i + 6].mType == ASMIT_ROL && mIns[i + 6].mMode == ASMIM_IMPLIED)
{
changed = true;
NativeCodeBasicBlock* eblock = proc->AllocateBlock();
NativeCodeBasicBlock* neblock = proc->AllocateBlock();
NativeCodeBasicBlock* rblock = proc->AllocateBlock();
rblock->mTrueJump = mTrueJump;
rblock->mFalseJump = mFalseJump;
rblock->mBranch = mBranch;
for (int j = i + 7; j < mIns.Size(); j++)
rblock->mIns.Push(mIns[j]);
mIns.SetSize(i + 1);
mIns[i + 0].mLive |= LIVE_CPU_REG_C;
mIns[i + 0].mType = ASMIT_ASL;
mTrueJump = neblock;
mFalseJump = eblock;
mBranch = ASMIT_BCS;
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
neblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0xff));
eblock->Close(rblock, nullptr, ASMIT_JMP);
neblock->Close(rblock, nullptr, ASMIT_JMP);
break;
}
if (mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 1].mType == ASMIT_ASL && mIns[i + 1].mMode == ASMIM_IMPLIED &&
mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0x00 &&
mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress == 0xff &&
mIns[i + 4].mType == ASMIT_EOR && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0xff &&
mIns[i + 5].mType == ASMIT_ASL && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 0].mAddress &&
mIns[i + 6].mType == ASMIT_ROL && mIns[i + 6].mMode == ASMIM_IMPLIED)
{
changed = true;
NativeCodeBasicBlock* eblock = proc->AllocateBlock();
NativeCodeBasicBlock* neblock = proc->AllocateBlock();
NativeCodeBasicBlock* rblock = proc->AllocateBlock();
rblock->mTrueJump = mTrueJump;
rblock->mFalseJump = mFalseJump;
rblock->mBranch = mBranch;
for (int j = i + 7; j < mIns.Size(); j++)
rblock->mIns.Push(mIns[j]);
mIns.SetSize(i + 1);
mIns[i + 0].mLive |= LIVE_CPU_REG_C;
mIns.Insert(i + 0, NativeCodeInstruction(ASMIT_ASL));
mTrueJump = neblock;
mFalseJump = eblock;
mBranch = ASMIT_BCS;
eblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
neblock->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0xff));
eblock->Close(rblock, nullptr, ASMIT_JMP);
neblock->Close(rblock, nullptr, ASMIT_JMP);
break;
}
}
#endif
#if 1
if (i + 6 < mIns.Size())
{
@ -16415,6 +16492,27 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
}
}
#endif
#if 1
if (mIns.Size() >= 1 && mIns[0].mType == ASMIT_TAY && !(mIns[0].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) && !mEntryRegA)
{
int i = 0;
while (i < mEntryBlocks.Size() && mEntryBlocks[i]->mIns.Size() > 0 && mEntryBlocks[i]->mIns.Last().mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDY, mEntryBlocks[i]->mIns.Last().mMode) && !mEntryBlocks[i]->mFalseJump)
i++;
if (i == mEntryBlocks.Size())
{
for (int i = 0; i < mEntryBlocks.Size(); i++)
{
NativeCodeBasicBlock* b = mEntryBlocks[i];
int sz = b->mIns.Size();
b->mIns[sz - 1].mType = ASMIT_LDY;
b->mIns[sz - 1].mLive |= LIVE_CPU_REG_Y;
changed = true;
}
mIns[0].mType = ASMIT_NOP; mIns[0].mMode = ASMIM_IMPLIED;
}
}
#endif
#if 1
if (mIns.Size() >= 1 && mIns[0].mMode == ASMIM_ABSOLUTE_X && !(mIns[0].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_Z)))
{
@ -21860,13 +21958,24 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo
#endif
// Check load and commutative with current accu value
#if 1
if (i + 1 < mIns.Size() && mIns[i].mType == ASMIT_LDA && mIns[i + 1].IsCommutative() && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mValue == mIns[i + 1].mAddress)
if (i + 1 < mIns.Size() && mIns[i].mType == ASMIT_LDA &&
mIns[i + 1].IsCommutative() && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mValue == mIns[i + 1].mAddress)
{
mIns[i].mType = mIns[i + 1].mType;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
changed = true;
}
#endif
#if 1
if (i + 2 < mIns.Size() && mIns[i].mType == ASMIT_LDA && mIns[i + 1].mType == ASMIT_CLC &&
mIns[i + 2].IsCommutative() && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE && mNDataSet.mRegs[CPU_REG_A].mValue == mIns[i + 2].mAddress)
{
mIns[i + 2].CopyMode(mIns[i + 0]);
mIns[i].mType = ASMIT_NOP; mIns[i].mMode = ASMIM_IMPLIED;
changed = true;
}
#endif
if (mIns[i].ValueForwarding(mNDataSet, carryop, !global, final))
changed = true;
if (carryop != ASMIT_NOP)
@ -31860,7 +31969,7 @@ void NativeCodeProcedure::CompressTemporaries(void)
else
mInterProc->mTempSize = tpos - BC_REG_TMP;
if (mNoFrame && !used[BC_REG_STACK] && mInterProc->mTempSize <= 16)
if (mNoFrame && !used[BC_REG_STACK] && mInterProc->mTempSize <= BC_REG_TMP_SAVED - BC_REG_TMP)
mStackExpand = 0;
}
}
@ -31924,7 +32033,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
mIndex = proc->mID;
int tempSave = proc->mTempSize > 16 && !proc->mSaveTempsLinkerObject && !mInterProc->mInterrupt ? proc->mTempSize - 16 : 0;
int tempSave = proc->mTempSize > BC_REG_TMP_SAVED - BC_REG_TMP && !proc->mSaveTempsLinkerObject && !mInterProc->mInterrupt ? proc->mTempSize - (BC_REG_TMP_SAVED - BC_REG_TMP) : 0;
int commonFrameSize = proc->mCommonFrameSize;
mStackExpand = tempSave + proc->mLocalSize;
@ -32007,7 +32116,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
int frameSpace = tempSave;
tempSave = proc->mTempSize > 16 ? proc->mTempSize - 16 : 0;
tempSave = proc->mTempSize > BC_REG_TMP_SAVED - BC_REG_TMP ? proc->mTempSize - (BC_REG_TMP_SAVED - BC_REG_TMP) : 0;
if (!(mGenerator->mCompilerOptions & COPT_NATIVE))
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BYTE, ASMIM_IMPLIED, 0xea));

View File

@ -74,7 +74,7 @@ int main2(int argc, const char** argv)
#else
strcpy(strProductName, "oscar64");
strcpy(strProductVersion, "1.13.178");
strcpy(strProductVersion, "1.14.179");
#ifdef __APPLE__
uint32_t length = sizeof(basePath);
@ -206,6 +206,10 @@ int main2(int argc, const char** argv)
if (arg[2] == '2')
compiler->mCompilerOptions |= COPT_VERBOSE2;
}
else if (arg[1] == 'x' && arg[2] == 'z')
{
compiler->mCompilerOptions |= COPT_EXTENDED_ZERO_PAGE;
}
else
compiler->mErrors->Error(loc, EERR_COMMAND_LINE, "Invalid command line argument", arg);
}

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,13,178,0
PRODUCTVERSION 1,13,178,0
FILEVERSION 1,14,179,0
PRODUCTVERSION 1,14,179,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -43,12 +43,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "oscar64"
VALUE "FileDescription", "oscar64 compiler"
VALUE "FileVersion", "1.13.178.0"
VALUE "FileVersion", "1.14.179.0"
VALUE "InternalName", "oscar64.exe"
VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "oscar64.exe"
VALUE "ProductName", "oscar64"
VALUE "ProductVersion", "1.13.178.0"
VALUE "ProductVersion", "1.14.179.0"
END
END
BLOCK "VarFileInfo"

View File

@ -4450,15 +4450,15 @@
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64"
"ProductCode" = "8:{9F4E2BAD-97D8-4D1A-981F-D6B719A704C0}"
"PackageCode" = "8:{9749B605-800D-406D-A8C7-759AA28CA93D}"
"ProductCode" = "8:{28347196-C1B9-4B31-9AAB-50EC7E4BFC8E}"
"PackageCode" = "8:{F19F2B8B-8649-4939-B1FA-8EF0A6862DD7}"
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:1.13.178"
"ProductVersion" = "8:1.14.179"
"Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:"

View File

@ -548,6 +548,7 @@ void screen_clear(void)
__interrupt void joy_interrupt()
{
// vic.color_border++;
// Poll joystick
joy_poll(0);
@ -580,6 +581,7 @@ __interrupt void joy_interrupt()
}
else if (CrossDelay > 0)
CrossDelay--;
// vic.color_border--;
}
enum GameState
@ -843,7 +845,7 @@ int main(void)
rirq_write(&bottom, 0, &vic.memptr, 0x27);
rirq_write(&bottom, 1, &vic.ctrl1, VIC_CTRL1_DEN | VIC_CTRL1_RSEL | 3);
rirq_call(&bottom, 2, joy_interrupt);
rirq_set(1, 250, &bottom);
rirq_set(1, 252, &bottom);
// sort the raster IRQs
rirq_sort();