More verbose debug output

This commit is contained in:
drmortalwombat 2022-04-25 07:57:31 +02:00
parent 3a689cc7a1
commit f619c5e0ab
11 changed files with 675 additions and 113 deletions

View File

@ -3,7 +3,7 @@
## History and motivation
It is a sad fact that the 6502 used in the Commodore64 and other home computers of the 80s is widely believet to have a poor code density when it comes to compiled or wider than eight bit code. The C standard requires computations to be made with ints which work best if they have the same size as a pointer.
It is a sad fact that the 6502 used in the Commodore64 and other home computers of the 80s is widely believed to have a poor code density when it comes to compiled or wider than eight bit code. The C standard requires computations to be made with ints which work best if they have the same size as a pointer.
The 6502 also has a very small stack of 256 bytes which cannot be easily addressed and thus cannot be used for local variables. Therefore a second stack for variables has to be maintained, resulting in costly indexing operations. The 6502 is also pretty poor when it comes to indexed operations, it has no index with constant offset addressing mode, and requires the y register to be used for indexing.
@ -66,9 +66,10 @@ The compiler is command line driven, and creates an executable .prg file.
oscar64 {-i=includePath} [-o=output.prg] [-rt=runtime.c] [-tf=format] [-e] [-n] [-dSYMBOL[=value]] {source.c}
* -v : verbose output for diagnostics
* -v2 : more verbose output
* -i : additional include paths
* -o : optional output file name
* -rt : alternative runtime library, replaces the crt.c
* -rt : alternative runtime library, replaces the crt.c (or empty for none)
* -e : execute the result in the integrated emulator
* -ep : execute and profile the result in the integrated emulator
* -n : create pure native code for all functions

View File

@ -124,12 +124,18 @@ void Compiler::CompileProcedure(InterCodeProcedure* proc)
if (proc->mNativeProcedure)
{
NativeCodeProcedure* ncproc = new NativeCodeProcedure(mNativeCodeGenerator);
if (mCompilerOptions & COPT_VERBOSE2)
printf("Generate native code <%s>\n", proc->mIdent->mString);
ncproc->Compile(proc);
}
else
{
ByteCodeProcedure* bgproc = new ByteCodeProcedure();
if (mCompilerOptions & COPT_VERBOSE2)
printf("Generate byte code <%s>\n", proc->mIdent->mString);
bgproc->Compile(mByteCodeGenerator, proc);
mByteCodeFunctions.Push(bgproc);
}
@ -213,6 +219,9 @@ bool Compiler::GenerateCode(void)
mGlobalAnalyzer->mCompilerOptions = mCompilerOptions;
if (mCompilerOptions & COPT_VERBOSE)
printf("Global analyzer\n");
mGlobalAnalyzer->AnalyzeAssembler(dcrtstart->mValue, nullptr);
for (int i = 0; i < mCompilationUnits->mReferenced.Size(); i++)
@ -230,6 +239,9 @@ bool Compiler::GenerateCode(void)
mNativeCodeGenerator->mCompilerOptions = mCompilerOptions;
mInterCodeModule->mCompilerOptions = mCompilerOptions;
if (mCompilerOptions & COPT_VERBOSE)
printf("Generate intermediate code\n");
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, dcrtstart->mValue, nullptr);
for (int i = 0; i < mCompilationUnits->mReferenced.Size(); i++)
{
@ -299,6 +311,9 @@ bool Compiler::GenerateCode(void)
if (mErrors->mErrorCount != 0)
return false;
if (mCompilerOptions & COPT_VERBOSE)
printf("Optimize static variable usage\n");
#if 1
for (int i = 0; i < mInterCodeModule->mProcedures.Size(); i++)
{
@ -311,6 +326,9 @@ bool Compiler::GenerateCode(void)
}
#endif
if (mCompilerOptions & COPT_VERBOSE)
printf("Generate native code\n");
for (int i = 0; i < mInterCodeModule->mProcedures.Size(); i++)
{
InterCodeProcedure* proc = mInterCodeModule->mProcedures[i];
@ -330,6 +348,9 @@ bool Compiler::GenerateCode(void)
LinkerObject* byteCodeObject = nullptr;
if (!(mCompilerOptions & COPT_NATIVE))
{
if (mCompilerOptions & COPT_VERBOSE)
printf("Generate byte code runtime\n");
// Compile used byte code functions
byteCodeObject = mLinker->AddObject(loc, Ident::Unique("bytecode"), sectionBytecode, LOT_RUNTIME);
@ -390,6 +411,9 @@ bool Compiler::GenerateCode(void)
for (int i = 0; i < mCompilationUnits->mReferenced.Size(); i++)
mLinker->ReferenceObject(mCompilationUnits->mReferenced[i]->mLinkerObject);
if (mCompilerOptions & COPT_VERBOSE)
printf("Link executable\n");
mLinker->Link();
return mErrors->mErrorCount == 0;

View File

@ -19,6 +19,7 @@ static const uint64 COPT_TARGET_COPY = 0x800000000ULL;
static const uint64 COPT_TARGET_BIN = 0x1000000000ULL;
static const uint64 COPT_VERBOSE = 0x1000000000ULL;
static const uint64 COPT_VERBOSE2 = 0x2000000000ULL;
static const uint64 COPT_NATIVE = 0x01000000;

View File

@ -2308,6 +2308,14 @@ bool InterOperand::IsUnsigned(void) const
}
void InterOperand::Forward(const InterOperand& op)
{
mTemp = op.mTemp;
mType = op.mType;
mRange = op.mRange;
mFinal = false;
}
bool InterOperand::IsEqual(const InterOperand& op) const
{
if (mType != op.mType || mTemp != op.mTemp)
@ -2720,6 +2728,15 @@ bool InterInstruction::RemoveUnusedResultInstructions(InterInstruction* pre, Num
else
requiredTemps -= mDst.mTemp;
}
else if (mCode == IC_LOAD_TEMPORARY && mDst.mTemp == mSrc[0].mTemp)
{
mCode = IC_NONE;
mDst.mTemp = -1;
for (int i = 0; i < mNumOperands; i++)
mSrc[i].mTemp = -1;
changed = true;
}
for (int i = 0; i < mNumOperands; i++)
{
@ -3275,6 +3292,16 @@ bool InterInstruction::ConstantFolding(void)
return true;
}
break;
case IC_LOAD_TEMPORARY:
if (mDst.mTemp == mSrc[0].mTemp)
{
mCode = IC_NONE;
mDst.mTemp = -1;
for (int i = 0; i < mNumOperands; i++)
mSrc[i].mTemp = -1;
return true;
}
break;
case IC_LEA:
if (mSrc[0].mTemp < 0 && mSrc[1].mTemp < 0)
{
@ -3482,7 +3509,7 @@ void InterInstruction::Disassemble(FILE* file)
}
InterCodeBasicBlock::InterCodeBasicBlock(void)
: mInstructions(nullptr), mEntryRenameTable(-1), mExitRenameTable(-1), mMergeTValues(nullptr), mTrueJump(nullptr), mFalseJump(nullptr), mLoopPrefix(nullptr), mDominator(nullptr),
: mInstructions(nullptr), mEntryRenameTable(-1), mExitRenameTable(-1), mMergeTValues(nullptr), mMergeAValues(nullptr), mTrueJump(nullptr), mFalseJump(nullptr), mLoopPrefix(nullptr), mDominator(nullptr),
mEntryValueRange(IntegerValueRange()), mTrueValueRange(IntegerValueRange()), mFalseValueRange(IntegerValueRange()), mLocalValueRange(IntegerValueRange()), mReverseValueRange(IntegerValueRange()), mEntryBlocks(nullptr), mLoadStoreInstructions(nullptr), mLoopPathBlocks(nullptr)
{
mInPath = false;
@ -6354,18 +6381,126 @@ bool InterCodeBasicBlock::RemoveUnusedStoreInstructions(const GrowingVariableArr
}
bool InterCodeBasicBlock::EliminateAliasValues(const GrowingInstructionPtrArray& tvalue, const GrowingInstructionPtrArray& avalue)
{
bool changed = false;
if (!mVisited)
{
GrowingInstructionPtrArray ltvalue(tvalue);
GrowingInstructionPtrArray lavalue(avalue);
if (mLoopHead)
{
ltvalue.Clear();
lavalue.Clear();
}
else if (mNumEntries > 0)
{
if (mNumEntered > 0)
{
for (int i = 0; i < ltvalue.Size(); i++)
{
if (mMergeTValues[i] != ltvalue[i])
ltvalue[i] = nullptr;
if (mMergeAValues[i] != lavalue[i])
lavalue[i] = nullptr;
}
for (int i = 0; i < ltvalue.Size(); i++)
{
if (lavalue[i] && !ltvalue[lavalue[i]->mSrc[0].mTemp])
lavalue[i] = nullptr;
}
}
mNumEntered++;
if (mNumEntered < mNumEntries)
{
mMergeTValues = ltvalue;
mMergeAValues = lavalue;
return false;
}
}
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 && lavalue[ins->mSrc[j].mTemp])
{
InterInstruction* mins = lavalue[ins->mSrc[j].mTemp];
if (mExitRequiredTemps[mins->mDst.mTemp] && !mExitRequiredTemps[mins->mSrc[0].mTemp])
{
ins->mSrc[j].Forward(mins->mDst);
changed = true;
}
}
}
if (ins->mDst.mTemp >= 0)
{
if (ltvalue[ins->mDst.mTemp] && ltvalue[ins->mDst.mTemp]->mCode == IC_LOAD_TEMPORARY)
lavalue[ltvalue[ins->mDst.mTemp]->mSrc[0].mTemp] = nullptr;
ltvalue[ins->mDst.mTemp] = ins;
lavalue[ins->mDst.mTemp] = nullptr;
if (ins->mCode == IC_LOAD_TEMPORARY)
lavalue[ins->mSrc[0].mTemp] = ins;
}
}
if (mTrueJump && mTrueJump->EliminateAliasValues(ltvalue, lavalue))
changed = true;
if (mFalseJump && mFalseJump->EliminateAliasValues(ltvalue, lavalue))
changed = true;
}
return changed;
}
bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArray& tvalue, int& spareTemps)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
GrowingInstructionPtrArray ltvalue(tvalue);
if (mNumEntries > 1)
if (mLoopHead)
{
ltvalue.Clear();
}
else if (mNumEntries > 0)
{
if (mNumEntered > 0)
{
for (int i = 0; i < ltvalue.Size(); i++)
{
if (mMergeTValues[i] != ltvalue[i])
ltvalue[i] = nullptr;
}
}
mNumEntered++;
if (mNumEntered < mNumEntries)
{
mMergeTValues = ltvalue;
return false;
}
}
mVisited = true;
for (int i = 0; i < mInstructions.Size(); i++)
{
@ -9268,6 +9403,11 @@ void InterCodeBasicBlock::PeepholeOptimization(void)
for (i = 0; i < mInstructions.Size(); i++)
{
if (mInstructions[i]->mCode == IC_LOAD_TEMPORARY && mInstructions[i]->mDst.mTemp == mInstructions[i]->mSrc->mTemp)
{
mInstructions[i]->mCode = IC_NONE;
changed = true;
}
if (i + 2 < mInstructions.Size())
{
if (mInstructions[i + 0]->mCode == IC_LOAD &&
@ -10534,6 +10674,17 @@ void InterCodeProcedure::Close(void)
#endif
GrowingInstructionPtrArray eivalues(nullptr);
do {
BuildDataFlowSets();
eivalues.SetSize(mTemporaries.Size(), true);
ResetVisited();
} while (mEntryBlock->EliminateAliasValues(eivalues, eivalues));
DisassembleDebug("EliminateAliasValues");
#if 1
if (mModule->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL)
{

View File

@ -252,6 +252,8 @@ public:
InterMemory mMemory;
IntegerValueRange mRange;
void Forward(const InterOperand& op);
InterOperand(void);
bool IsEqual(const InterOperand & op) const;
@ -354,7 +356,7 @@ public:
GrowingArray<InterCodeBasicBlock*> mEntryBlocks, mLoopPathBlocks;
GrowingInstructionPtrArray mMergeTValues;
GrowingInstructionPtrArray mMergeTValues, mMergeAValues;
ValueSet mMergeValues;
TempForwardingTable mMergeForwardingTable;
@ -419,6 +421,7 @@ public:
bool EliminateDeadBranches(void);
bool SimplifyIntegerNumeric(const GrowingInstructionPtrArray& tvalue, int& spareTemps);
bool EliminateAliasValues(const GrowingInstructionPtrArray& tvalue, const GrowingInstructionPtrArray& avalue);
bool CalculateSingleAssignmentTemps(FastNumberSet& tassigned, GrowingInstructionPtrArray& tvalue, NumberSet& modifiedParams, InterMemory paramMemory);
bool SingleAssignmentTempForwarding(const GrowingInstructionPtrArray& tunified, const GrowingInstructionPtrArray& tvalues);

View File

@ -3556,7 +3556,12 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod
InterCodeBasicBlock* exitBlock = entryBlock;
if (dec->mFlags & DTF_DEFINED)
{
if (mCompilerOptions & COPT_VERBOSE2)
printf("Generate intermediate code <%s>\n", proc->mIdent->mString);
TranslateExpression(dec->mBase, proc, exitBlock, exp, nullptr, nullptr, nullptr);
}
else
mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->mIdent->mString);
@ -3566,7 +3571,12 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod
exitBlock->Close(nullptr, nullptr);
if (mErrors->mErrorCount == 0)
{
if (mCompilerOptions & COPT_VERBOSE2)
printf("Optimize intermediate code <%s>\n", proc->mIdent->mString);
proc->Close();
}
return proc;
}

View File

@ -302,21 +302,30 @@ void Linker::Link(void)
for (int k = 0; k < lsec->mObjects.Size(); k++)
{
LinkerObject* lobj = lsec->mObjects[k];
if ((lobj->mFlags & LOBJF_REFERENCED) && !(lobj->mFlags & LOBJF_PLACED) && lrgn->Allocate(this, lobj) )
if ((lobj->mFlags & LOBJF_REFERENCED) && !(lobj->mFlags & LOBJF_PLACED) && lrgn->Allocate(this, lobj))
{
if (lsec->mType != LST_BSS || lobj->mAddress + lobj->mSize == lrgn->mStart + lrgn->mUsed)
{
if (lobj->mAddress < lsec->mStart)
lsec->mStart = lobj->mAddress;
if (lobj->mAddress + lobj->mSize > lsec->mEnd)
lsec->mEnd = lobj->mAddress + lobj->mSize;
}
if (lobj->mIdent && lobj->mIdent->mString && (mCompilerOptions & COPT_VERBOSE2))
printf("Placed object <%s> $%04x - $%04x\n", lobj->mIdent->mString, lobj->mAddress, lobj->mAddress + lobj->mSize);
if (lobj->mAddress < lsec->mStart)
lsec->mStart = lobj->mAddress;
if (lobj->mAddress + lobj->mSize > lsec->mEnd)
lsec->mEnd = lobj->mAddress + lobj->mSize;
if (lsec->mType == LST_DATA && lsec->mEnd > lrgn->mNonzero)
lrgn->mNonzero = lsec->mEnd;
}
}
}
for (int j = 0; j < lrgn->mSections.Size(); j++)
{
LinkerSection* lsec = lrgn->mSections[j];
if (lsec->mType == LST_BSS && lsec->mStart < lrgn->mNonzero)
lsec->mStart = lrgn->mNonzero;
if (lsec->mEnd < lsec->mStart)
lsec->mEnd = lsec->mStart;
}
}
mProgramStart = 0xffff;

File diff suppressed because it is too large Load Diff

View File

@ -73,7 +73,7 @@ int main2(int argc, const char** argv)
#else
strcpy(strProductName, "oscar64");
strcpy(strProductVersion, "1.5.120");
strcpy(strProductVersion, "1.5.121");
#ifdef __APPLE__
uint32_t length = sizeof(basePath);
@ -178,7 +178,11 @@ int main2(int argc, const char** argv)
compiler->AddDefine(Ident::Unique(def), "");
}
else if (arg[1] == 'v')
{
compiler->mCompilerOptions |= COPT_VERBOSE;
if (arg[2] == '2')
compiler->mCompilerOptions |= COPT_VERBOSE2;
}
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,5,120,0
PRODUCTVERSION 1,5,120,0
FILEVERSION 1,5,121,0
PRODUCTVERSION 1,5,121,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -43,12 +43,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "oscar64"
VALUE "FileDescription", "oscar64 compiler"
VALUE "FileVersion", "1.5.120.0"
VALUE "FileVersion", "1.5.121.0"
VALUE "InternalName", "oscar64.exe"
VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "oscar64.exe"
VALUE "ProductName", "oscar64"
VALUE "ProductVersion", "1.5.120.0"
VALUE "ProductVersion", "1.5.121.0"
END
END
BLOCK "VarFileInfo"

View File

@ -4023,15 +4023,15 @@
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64"
"ProductCode" = "8:{9290BC82-2F82-425B-940E-E5626BB5D5FD}"
"PackageCode" = "8:{B19DA3BE-65E1-4E1E-B167-39662B0C378C}"
"ProductCode" = "8:{9712E64F-8FDC-4FD2-BE20-8889E458BC89}"
"PackageCode" = "8:{63C93E1F-200E-43F4-8A18-C9A7743F2543}"
"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.5.120"
"ProductVersion" = "8:1.5.121"
"Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:"
@ -4545,7 +4545,7 @@
{
"{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_FB2E467BC172457785F4279BB0BFE8B6"
{
"SourcePath" = "8:..\\Release\\oscar64.exe"
"SourcePath" = "8:..\\Debug\\oscar64.exe"
"TargetName" = "8:"
"Tag" = "8:"
"Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4"