Static call graph analysis for function arguments
This commit is contained in:
parent
761206d009
commit
02db5b5eb1
|
@ -83,6 +83,7 @@ The compiler is command line driven, and creates an executable .prg file.
|
||||||
* -d64 : create a d64 disk image
|
* -d64 : create a d64 disk image
|
||||||
* -f : add a binary file to the disk image
|
* -f : add a binary file to the disk image
|
||||||
* -fz : add a compressed 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.
|
A list of source files can be provided.
|
||||||
|
|
|
@ -49,6 +49,22 @@ void Compiler::AddDefine(const Ident* ident, const char* value)
|
||||||
|
|
||||||
bool Compiler::ParseSource(void)
|
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;
|
mPreprocessor->mCompilerOptions = mCompilerOptions;
|
||||||
mLinker->mCompilerOptions = mCompilerOptions;
|
mLinker->mCompilerOptions = mCompilerOptions;
|
||||||
|
|
||||||
|
@ -220,6 +236,8 @@ bool Compiler::GenerateCode(void)
|
||||||
regionMain->mSections.Push(mCompilationUnits->mSectionStack);
|
regionMain->mSections.Push(mCompilationUnits->mSectionStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mInterCodeModule->InitParamStack(mCompilationUnits->mSectionStack);
|
||||||
|
|
||||||
dcrtstart->mSection = sectionStartup;
|
dcrtstart->mSection = sectionStartup;
|
||||||
|
|
||||||
mGlobalAnalyzer->mCompilerOptions = mCompilerOptions;
|
mGlobalAnalyzer->mCompilerOptions = mCompilerOptions;
|
||||||
|
|
|
@ -12,6 +12,8 @@ static const uint64 COPT_OPTIMIZE_CONST_EXPRESSIONS = 0x00000080;
|
||||||
|
|
||||||
static const uint64 COPT_OPTIMIZE_CODE_SIZE = 0x00000100;
|
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_PRG = 0x100000000ULL;
|
||||||
static const uint64 COPT_TARGET_CRT16 = 0x200000000ULL;
|
static const uint64 COPT_TARGET_CRT16 = 0x200000000ULL;
|
||||||
static const uint64 COPT_TARGET_CRT512 = 0x400000000ULL;
|
static const uint64 COPT_TARGET_CRT512 = 0x400000000ULL;
|
||||||
|
|
|
@ -797,7 +797,7 @@ const char* NativeCodeDisassembler::TempName(uint8 tmp, char* buffer, InterCodeP
|
||||||
sprintf_s(buffer, 10, "P%d", tmp - BC_REG_FPARAMS);
|
sprintf_s(buffer, 10, "P%d", tmp - BC_REG_FPARAMS);
|
||||||
return buffer;
|
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);
|
sprintf_s(buffer, 10, "FP + %d", tmp - BC_REG_LOCALS);
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
|
@ -156,25 +156,52 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec)
|
||||||
nbase = 1000;
|
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 (procDec->mBase->mBase->mType == DT_TYPE_STRUCT)
|
||||||
|
{
|
||||||
|
if (nbase < numfpzero && nbase + 2 > numfpzero)
|
||||||
|
nbase = numfpzero;
|
||||||
nparams += 2;
|
nparams += 2;
|
||||||
|
}
|
||||||
|
|
||||||
Declaration* dec = procDec->mBase->mParams;
|
Declaration* dec = procDec->mBase->mParams;
|
||||||
while (dec)
|
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;
|
nparams += dec->mBase->mSize;
|
||||||
dec = dec->mNext;
|
dec = dec->mNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbase + nparams <= BC_REG_FPARAMS_END - BC_REG_FPARAMS)
|
if (nbase + nparams <= fplimit)
|
||||||
{
|
{
|
||||||
procDec->mFastCallBase = nbase;
|
procDec->mFastCallBase = nbase;
|
||||||
procDec->mFastCallSize = nparams;
|
procDec->mFastCallSize = nparams;
|
||||||
procDec->mBase->mFastCallBase = nbase;
|
procDec->mBase->mFastCallBase = nbase;
|
||||||
procDec->mBase->mFastCallSize = nparams;
|
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;
|
procDec->mBase->mFlags |= DTF_FASTCALL;
|
||||||
#if 0
|
#if 0
|
||||||
printf("FASTCALL %s\n", f->mIdent->mString);
|
printf("FASTCALL %s\n", f->mIdent->mString);
|
||||||
|
@ -410,6 +437,12 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec)
|
||||||
return exp->mDecValue->mBase;
|
return exp->mDecValue->mBase;
|
||||||
case EX_CALL:
|
case EX_CALL:
|
||||||
ldec = Analyze(exp->mLeft, procDec);
|
ldec = Analyze(exp->mLeft, procDec);
|
||||||
|
if ((ldec->mFlags & DTF_INTRINSIC) && !ldec->mValue)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
RegisterCall(procDec, ldec);
|
RegisterCall(procDec, ldec);
|
||||||
if (!(GetProcFlags(ldec) & (DTF_FUNC_INTRSAVE | DTF_INTERRUPT)))
|
if (!(GetProcFlags(ldec) & (DTF_FUNC_INTRSAVE | DTF_INTERRUPT)))
|
||||||
{
|
{
|
||||||
|
@ -417,9 +450,26 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec)
|
||||||
if (procDec->mFlags & DTF_INTERRUPT)
|
if (procDec->mFlags & DTF_INTERRUPT)
|
||||||
mErrors->Error(exp->mLocation, EWARN_NOT_INTERRUPT_SAFE, "Calling non interrupt safe function", ldec->mIdent);
|
mErrors->Error(exp->mLocation, EWARN_NOT_INTERRUPT_SAFE, "Calling non interrupt safe function", ldec->mIdent);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (exp->mRight)
|
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));
|
RegisterProc(Analyze(exp->mRight, procDec));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EX_LIST:
|
case EX_LIST:
|
||||||
RegisterProc(Analyze(exp->mLeft, procDec));
|
RegisterProc(Analyze(exp->mLeft, procDec));
|
||||||
|
|
|
@ -85,7 +85,7 @@ void IntegerValueRange::LimitMaxBound(int64 value)
|
||||||
|
|
||||||
void IntegerValueRange::LimitMinWeak(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;
|
mMinState = S_BOUND;
|
||||||
mMinValue = value;
|
mMinValue = value;
|
||||||
|
@ -95,7 +95,7 @@ void IntegerValueRange::LimitMinWeak(int64 value)
|
||||||
|
|
||||||
void IntegerValueRange::LimitMaxWeak(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;
|
mMaxState = S_BOUND;
|
||||||
mMaxValue = value;
|
mMaxValue = value;
|
||||||
|
@ -6130,6 +6130,7 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
|
||||||
default:
|
default:
|
||||||
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
|
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
if (ins->mDst.mType == IT_INT8)
|
if (ins->mDst.mType == IT_INT8)
|
||||||
{
|
{
|
||||||
|
@ -6600,6 +6601,11 @@ void InterCodeBasicBlock::RestartLocalIntegerRangeSets(int num, const GrowingVar
|
||||||
mMemoryValueSize.SetSize(num, false);
|
mMemoryValueSize.SetSize(num, false);
|
||||||
mEntryMemoryValueSize.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++)
|
for (int i = 0; i < mEntryValueRange.Size(); i++)
|
||||||
{
|
{
|
||||||
IntegerValueRange& vr(mEntryValueRange[i]);
|
IntegerValueRange& vr(mEntryValueRange[i]);
|
||||||
|
@ -10095,7 +10101,7 @@ void InterCodeBasicBlock::CollectStaticStack(LinkerObject* lobj, const GrowingVa
|
||||||
lobj->mStackSection->mSections.Push(mInstructions[i]->mSrc[0].mLinkerObject->mStackSection);
|
lobj->mStackSection->mSections.Push(mInstructions[i]->mSrc[0].mLinkerObject->mStackSection);
|
||||||
|
|
||||||
if (mInstructions[i]->mCode == IC_LOAD)
|
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)
|
else if (mInstructions[i]->mCode == IC_STORE || mInstructions[i]->mCode == IC_LEA)
|
||||||
ApplyStaticStack(mInstructions[i]->mSrc[1], localVars);
|
ApplyStaticStack(mInstructions[i]->mSrc[1], localVars);
|
||||||
else if (mInstructions[i]->mCode == IC_CONSTANT && mInstructions[i]->mDst.mType == IT_POINTER)
|
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)
|
bool InterCodeBasicBlock::DropUnreachable(void)
|
||||||
{
|
{
|
||||||
if (!mVisited)
|
if (!mVisited)
|
||||||
|
@ -14333,6 +14380,7 @@ void InterCodeProcedure::Close(void)
|
||||||
{
|
{
|
||||||
mLinkerObject->mFlags |= LOBJF_STATIC_STACK;
|
mLinkerObject->mFlags |= LOBJF_STATIC_STACK;
|
||||||
mLinkerObject->mStackSection = mModule->mLinker->AddSection(mIdent->Mangle("@stack"), LST_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++)
|
for (int i = 0; i < mLocalVars.Size(); i++)
|
||||||
{
|
{
|
||||||
|
@ -14458,14 +14506,17 @@ void InterCodeProcedure::Close(void)
|
||||||
|
|
||||||
MapCallerSavedTemps();
|
MapCallerSavedTemps();
|
||||||
|
|
||||||
|
ResetVisited();
|
||||||
|
mEntryBlock->PromoteStaticStackParams(mModule->mParamLinkerObject);
|
||||||
|
|
||||||
if (mValueReturn)
|
if (mValueReturn)
|
||||||
{
|
{
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->CheckValueReturn(this);
|
mEntryBlock->CheckValueReturn(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSaveTempsLinkerObject && mTempSize > 16)
|
if (mSaveTempsLinkerObject && mTempSize > BC_REG_TMP_SAVED - BC_REG_TMP)
|
||||||
mSaveTempsLinkerObject->AddSpace(mTempSize - 16);
|
mSaveTempsLinkerObject->AddSpace(mTempSize - (BC_REG_TMP_SAVED - BC_REG_TMP));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterCodeProcedure::AddCalledFunction(InterCodeProcedure* proc)
|
void InterCodeProcedure::AddCalledFunction(InterCodeProcedure* proc)
|
||||||
|
@ -14867,10 +14918,10 @@ void InterCodeProcedure::MapCallerSavedTemps(void)
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->BuildCallerSaveTempSet(callerSaved);
|
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)
|
if (mCallsFunctionPointer)
|
||||||
freeCallerSavedTemps = 16;
|
freeCallerSavedTemps = BC_REG_TMP_SAVED - BC_REG_TMP;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < mCalledFunctions.Size(); i++)
|
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]);
|
printf("T%02d : %d, %d\n", i, mTempOffset[i], mTempSizes[i]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (mSaveTempsLinkerObject && mTempSize > 16)
|
if (mSaveTempsLinkerObject && mTempSize > BC_REG_TMP_SAVED - BC_REG_TMP)
|
||||||
mSaveTempsLinkerObject->AddSpace(mTempSize - 16);
|
mSaveTempsLinkerObject->AddSpace(mTempSize - (BC_REG_TMP_SAVED - BC_REG_TMP));
|
||||||
|
|
||||||
// printf("Map %s, %d, %d, %d, %d\n", mIdent->mString, freeTemps, callerSavedTemps, calleeSavedTemps, freeCallerSavedTemps);
|
// 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)
|
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)
|
bool InterCodeModule::Disassemble(const char* filename)
|
||||||
{
|
{
|
||||||
FILE* file;
|
FILE* file;
|
||||||
|
|
|
@ -518,6 +518,7 @@ public:
|
||||||
|
|
||||||
bool CheckStaticStack(void);
|
bool CheckStaticStack(void);
|
||||||
void CollectStaticStack(LinkerObject * lobj, const GrowingVariableArray& localVars);
|
void CollectStaticStack(LinkerObject * lobj, const GrowingVariableArray& localVars);
|
||||||
|
void PromoteStaticStackParams(LinkerObject* paramlobj);
|
||||||
|
|
||||||
bool SameExitCode(const InterCodeBasicBlock* block) const;
|
bool SameExitCode(const InterCodeBasicBlock* block) const;
|
||||||
|
|
||||||
|
@ -622,11 +623,15 @@ public:
|
||||||
InterCodeModule(Errors* errors, Linker * linker);
|
InterCodeModule(Errors* errors, Linker * linker);
|
||||||
~InterCodeModule(void);
|
~InterCodeModule(void);
|
||||||
|
|
||||||
|
void InitParamStack(LinkerSection * stackSection);
|
||||||
|
|
||||||
bool Disassemble(const char* name);
|
bool Disassemble(const char* name);
|
||||||
|
|
||||||
GrowingInterCodeProcedurePtrArray mProcedures;
|
GrowingInterCodeProcedurePtrArray mProcedures;
|
||||||
|
|
||||||
GrowingVariableArray mGlobalVars;
|
GrowingVariableArray mGlobalVars;
|
||||||
|
LinkerObject * mParamLinkerObject;
|
||||||
|
LinkerSection * mParamLinkerSection;
|
||||||
|
|
||||||
Linker * mLinker;
|
Linker * mLinker;
|
||||||
Errors* mErrors;
|
Errors* mErrors;
|
||||||
|
|
|
@ -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)
|
InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper* inlineMapper, ExValue* lrexp)
|
||||||
{
|
{
|
||||||
Declaration* dec;
|
Declaration* dec;
|
||||||
|
@ -2048,179 +2228,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
|
|
||||||
if (doInline)
|
if (doInline)
|
||||||
{
|
{
|
||||||
Declaration* fdec = exp->mLeft->mDecValue;
|
return TranslateInline(procType, proc, block, exp, breakBlock, continueBlock, inlineMapper, inlineConstexpr);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -58,6 +58,7 @@ protected:
|
||||||
ExValue CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, Declaration * type);
|
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);
|
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);
|
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);
|
void BuildInitializer(InterCodeModule* mod, uint8 * dp, int offset, Declaration* data, InterVariable * variable);
|
||||||
};
|
};
|
||||||
|
|
|
@ -71,6 +71,12 @@ void LinkerObject::AddData(const uint8* data, int size)
|
||||||
memcpy(mData, data, size);
|
memcpy(mData, data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LinkerObject::EnsureSpace(int offset, int size)
|
||||||
|
{
|
||||||
|
if (offset + size > mSize)
|
||||||
|
AddSpace(offset + size);
|
||||||
|
}
|
||||||
|
|
||||||
uint8* LinkerObject::AddSpace(int size)
|
uint8* LinkerObject::AddSpace(int size)
|
||||||
{
|
{
|
||||||
if (mSize != size)
|
if (mSize != size)
|
||||||
|
|
|
@ -174,6 +174,7 @@ public:
|
||||||
|
|
||||||
void AddData(const uint8* data, int size);
|
void AddData(const uint8* data, int size);
|
||||||
uint8* AddSpace(int size);
|
uint8* AddSpace(int size);
|
||||||
|
void EnsureSpace(int offset, int size);
|
||||||
|
|
||||||
GrowingArray<LinkerReference*> mReferences;
|
GrowingArray<LinkerReference*> mReferences;
|
||||||
|
|
||||||
|
|
|
@ -13750,6 +13750,83 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
|
||||||
|
|
||||||
for (int i = 0; i < mIns.Size(); i++)
|
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 1
|
||||||
if (i + 6 < mIns.Size())
|
if (i + 6 < mIns.Size())
|
||||||
{
|
{
|
||||||
|
@ -16415,6 +16492,27 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#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 1
|
||||||
if (mIns.Size() >= 1 && mIns[0].mMode == ASMIM_ABSOLUTE_X && !(mIns[0].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_Z)))
|
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
|
#endif
|
||||||
// Check load and commutative with current accu value
|
// Check load and commutative with current accu value
|
||||||
#if 1
|
#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].mType = mIns[i + 1].mType;
|
||||||
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
|
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
#endif
|
#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))
|
if (mIns[i].ValueForwarding(mNDataSet, carryop, !global, final))
|
||||||
changed = true;
|
changed = true;
|
||||||
if (carryop != ASMIT_NOP)
|
if (carryop != ASMIT_NOP)
|
||||||
|
@ -31860,7 +31969,7 @@ void NativeCodeProcedure::CompressTemporaries(void)
|
||||||
else
|
else
|
||||||
mInterProc->mTempSize = tpos - BC_REG_TMP;
|
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;
|
mStackExpand = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31924,7 +32033,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
|
|
||||||
mIndex = proc->mID;
|
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;
|
int commonFrameSize = proc->mCommonFrameSize;
|
||||||
|
|
||||||
mStackExpand = tempSave + proc->mLocalSize;
|
mStackExpand = tempSave + proc->mLocalSize;
|
||||||
|
@ -32007,7 +32116,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
|
|
||||||
int frameSpace = tempSave;
|
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))
|
if (!(mGenerator->mCompilerOptions & COPT_NATIVE))
|
||||||
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BYTE, ASMIM_IMPLIED, 0xea));
|
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_BYTE, ASMIM_IMPLIED, 0xea));
|
||||||
|
|
|
@ -74,7 +74,7 @@ int main2(int argc, const char** argv)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
strcpy(strProductName, "oscar64");
|
strcpy(strProductName, "oscar64");
|
||||||
strcpy(strProductVersion, "1.13.178");
|
strcpy(strProductVersion, "1.14.179");
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
uint32_t length = sizeof(basePath);
|
uint32_t length = sizeof(basePath);
|
||||||
|
@ -206,6 +206,10 @@ int main2(int argc, const char** argv)
|
||||||
if (arg[2] == '2')
|
if (arg[2] == '2')
|
||||||
compiler->mCompilerOptions |= COPT_VERBOSE2;
|
compiler->mCompilerOptions |= COPT_VERBOSE2;
|
||||||
}
|
}
|
||||||
|
else if (arg[1] == 'x' && arg[2] == 'z')
|
||||||
|
{
|
||||||
|
compiler->mCompilerOptions |= COPT_EXTENDED_ZERO_PAGE;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
compiler->mErrors->Error(loc, EERR_COMMAND_LINE, "Invalid command line argument", arg);
|
compiler->mErrors->Error(loc, EERR_COMMAND_LINE, "Invalid command line argument", arg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,13,178,0
|
FILEVERSION 1,14,179,0
|
||||||
PRODUCTVERSION 1,13,178,0
|
PRODUCTVERSION 1,14,179,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -43,12 +43,12 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "oscar64"
|
VALUE "CompanyName", "oscar64"
|
||||||
VALUE "FileDescription", "oscar64 compiler"
|
VALUE "FileDescription", "oscar64 compiler"
|
||||||
VALUE "FileVersion", "1.13.178.0"
|
VALUE "FileVersion", "1.14.179.0"
|
||||||
VALUE "InternalName", "oscar64.exe"
|
VALUE "InternalName", "oscar64.exe"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2021"
|
VALUE "LegalCopyright", "Copyright (C) 2021"
|
||||||
VALUE "OriginalFilename", "oscar64.exe"
|
VALUE "OriginalFilename", "oscar64.exe"
|
||||||
VALUE "ProductName", "oscar64"
|
VALUE "ProductName", "oscar64"
|
||||||
VALUE "ProductVersion", "1.13.178.0"
|
VALUE "ProductVersion", "1.14.179.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -4450,15 +4450,15 @@
|
||||||
{
|
{
|
||||||
"Name" = "8:Microsoft Visual Studio"
|
"Name" = "8:Microsoft Visual Studio"
|
||||||
"ProductName" = "8:oscar64"
|
"ProductName" = "8:oscar64"
|
||||||
"ProductCode" = "8:{9F4E2BAD-97D8-4D1A-981F-D6B719A704C0}"
|
"ProductCode" = "8:{28347196-C1B9-4B31-9AAB-50EC7E4BFC8E}"
|
||||||
"PackageCode" = "8:{9749B605-800D-406D-A8C7-759AA28CA93D}"
|
"PackageCode" = "8:{F19F2B8B-8649-4939-B1FA-8EF0A6862DD7}"
|
||||||
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
|
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
|
||||||
"AspNetVersion" = "8:2.0.50727.0"
|
"AspNetVersion" = "8:2.0.50727.0"
|
||||||
"RestartWWWService" = "11:FALSE"
|
"RestartWWWService" = "11:FALSE"
|
||||||
"RemovePreviousVersions" = "11:TRUE"
|
"RemovePreviousVersions" = "11:TRUE"
|
||||||
"DetectNewerInstalledVersion" = "11:TRUE"
|
"DetectNewerInstalledVersion" = "11:TRUE"
|
||||||
"InstallAllUsers" = "11:FALSE"
|
"InstallAllUsers" = "11:FALSE"
|
||||||
"ProductVersion" = "8:1.13.178"
|
"ProductVersion" = "8:1.14.179"
|
||||||
"Manufacturer" = "8:oscar64"
|
"Manufacturer" = "8:oscar64"
|
||||||
"ARPHELPTELEPHONE" = "8:"
|
"ARPHELPTELEPHONE" = "8:"
|
||||||
"ARPHELPLINK" = "8:"
|
"ARPHELPLINK" = "8:"
|
||||||
|
|
|
@ -548,6 +548,7 @@ void screen_clear(void)
|
||||||
|
|
||||||
__interrupt void joy_interrupt()
|
__interrupt void joy_interrupt()
|
||||||
{
|
{
|
||||||
|
// vic.color_border++;
|
||||||
// Poll joystick
|
// Poll joystick
|
||||||
joy_poll(0);
|
joy_poll(0);
|
||||||
|
|
||||||
|
@ -580,6 +581,7 @@ __interrupt void joy_interrupt()
|
||||||
}
|
}
|
||||||
else if (CrossDelay > 0)
|
else if (CrossDelay > 0)
|
||||||
CrossDelay--;
|
CrossDelay--;
|
||||||
|
// vic.color_border--;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum GameState
|
enum GameState
|
||||||
|
@ -843,7 +845,7 @@ int main(void)
|
||||||
rirq_write(&bottom, 0, &vic.memptr, 0x27);
|
rirq_write(&bottom, 0, &vic.memptr, 0x27);
|
||||||
rirq_write(&bottom, 1, &vic.ctrl1, VIC_CTRL1_DEN | VIC_CTRL1_RSEL | 3);
|
rirq_write(&bottom, 1, &vic.ctrl1, VIC_CTRL1_DEN | VIC_CTRL1_RSEL | 3);
|
||||||
rirq_call(&bottom, 2, joy_interrupt);
|
rirq_call(&bottom, 2, joy_interrupt);
|
||||||
rirq_set(1, 250, &bottom);
|
rirq_set(1, 252, &bottom);
|
||||||
|
|
||||||
// sort the raster IRQs
|
// sort the raster IRQs
|
||||||
rirq_sort();
|
rirq_sort();
|
||||||
|
|
Loading…
Reference in New Issue