diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 9ca98cf..fa07d1d 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -135,6 +135,9 @@ rem @echo off @call :test ptrarraycmptest.c @if %errorlevel% neq 0 goto :error +@call :test cplxstructtest.c +@if %errorlevel% neq 0 goto :error + @exit /b 0 :error diff --git a/autotest/bitshifttest.c b/autotest/bitshifttest.c index 029b5d1..63d914a 100644 --- a/autotest/bitshifttest.c +++ b/autotest/bitshifttest.c @@ -362,6 +362,7 @@ int main(void) shr16b(0xfedc, 0xfedc); shl16n(0x0000, 0x0000); + shl16n(0xffff, 0xffff); shl16n(0x1234, 0x1234); shl16n(0xfedc, 0xfedc); diff --git a/autotest/cplxstructtest.c b/autotest/cplxstructtest.c new file mode 100644 index 0000000..1fb8a7f --- /dev/null +++ b/autotest/cplxstructtest.c @@ -0,0 +1,97 @@ +#include +#include +#include + +struct cplx +{ + float r, i; +}; + +cplx cplx_add(cplx a, cplx b) +{ + cplx c; + c.r = a.r + b.r; + c.i = a.i + b.i; + return c; +} + +cplx cplx_sub(cplx a, cplx b) +{ + cplx c; + c.r = a.r - b.r; + c.i = a.i - b.i; + return c; +} + +cplx cplx_mul(cplx a, cplx b) +{ + cplx c; + c.r = a.r * b.r - a.i * b.i; + c.i = a.i * b.r + a.r * b.i; + return c; +} + +float cplx_abs(cplx a) +{ + return sqrt(a.r * a.r + a.i * a.i); +} + +cplx cplx_sum(cplx p, const cplx * a, int n) +{ + cplx s = {0.0, 0.0}; + cplx c = {1.0, 0.0}; + + for(int i=0; imSectionCode); - mInterCodeModule = new InterCodeModule(); + mInterCodeModule = new InterCodeModule(mLinker); mGlobalAnalyzer = new GlobalAnalyzer(mErrors, mLinker); } @@ -311,6 +311,9 @@ bool Compiler::GenerateCode(void) #endif CompileProcedure(proc); + + if (proc->mLinkerObject->mStackSection) + mCompilationUnits->mSectionStack->mSections.Push(proc->mLinkerObject->mStackSection); } LinkerObject* byteCodeObject = nullptr; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index aacc034..a30f652 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -127,7 +127,7 @@ void GlobalAnalyzer::AutoInline(void) void GlobalAnalyzer::CheckFastcall(Declaration* procDec) { - if (!(procDec->mBase->mFlags & DTF_FASTCALL) && !(procDec->mBase->mFlags & DTF_STACKCALL)) + if (!(procDec->mBase->mFlags & DTF_FASTCALL) && !(procDec->mBase->mFlags & DTF_STACKCALL) && (procDec->mType == DT_CONST_FUNCTION)) { if (!(procDec->mBase->mFlags & DTF_VARIADIC) && !(procDec->mFlags & DTF_FUNC_VARIABLE) && !(procDec->mFlags & DTF_FUNC_RECURSIVE)) { @@ -150,6 +150,10 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec) } int nparams = 0; + + if (procDec->mBase->mBase->mType == DT_TYPE_STRUCT) + nparams += 2; + Declaration* dec = procDec->mBase->mParams; while (dec) { diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 47a5b67..5dc6053 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -2702,6 +2702,13 @@ bool InterInstruction::ConstantFolding(void) mNumOperands = 1; return true; } + else if ((mOperator == IA_AND || mOperator == IA_MUL || mOperator == IA_SHL || mOperator == IA_SHR || mOperator == IA_SAR) && mSrc[1].mIntConst == 0) + { + mCode = IC_CONSTANT; + mConst.mIntConst = 0; + mNumOperands = 0; + return true; + } } } #endif @@ -6954,6 +6961,65 @@ bool InterCodeBasicBlock::IsEqual(const InterCodeBasicBlock* block) const return false; } +bool InterCodeBasicBlock::CheckStaticStack(void) +{ + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i < mInstructions.Size(); i++) + { + if (mInstructions[i]->mCode == IC_CALL || mInstructions[i]->mCode == IC_CALL_NATIVE) + { + if (mInstructions[i]->mSrc[0].mTemp >= 0 || !mInstructions[i]->mSrc[0].mLinkerObject) + return false; + else if (!(mInstructions[i]->mSrc[0].mLinkerObject->mFlags & LOBJF_STATIC_STACK)) + return false; + } + } + + if (mTrueJump && !mTrueJump->CheckStaticStack()) + return false; + if (mFalseJump && !mFalseJump->CheckStaticStack()) + return false; + } + + return true; +} + +void ApplyStaticStack(InterOperand & iop, const GrowingVariableArray& localVars) +{ + if (iop.mMemory == IM_LOCAL) + { + iop.mMemory = IM_GLOBAL; + iop.mLinkerObject = localVars[iop.mVarIndex]->mLinkerObject; + } +} + +void InterCodeBasicBlock::CollectStaticStack(LinkerObject* lobj, const GrowingVariableArray& localVars) +{ + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i < mInstructions.Size(); i++) + { + if (mInstructions[i]->mCode == IC_CALL || mInstructions[i]->mCode == IC_CALL_NATIVE) + lobj->mStackSection->mSections.Push(mInstructions[i]->mSrc[0].mLinkerObject->mStackSection); + + if (mInstructions[i]->mCode == IC_LOAD) + 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) + ApplyStaticStack(mInstructions[i]->mConst, localVars); + } + + if (mTrueJump) mTrueJump->CollectStaticStack(lobj, localVars); + if (mFalseJump) mFalseJump->CollectStaticStack(lobj, localVars); + } +} + bool InterCodeBasicBlock::DropUnreachable(void) { if (!mVisited) @@ -7243,7 +7309,7 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) for (int i = 0; i < path.Size(); i++) printf("path %d\n", path[i]->mIndex); #endif - bool hasCall = false; + bool hasCall = false, hasFrame = false; for (int bi = 0; bi < body.Size(); bi++) { InterCodeBasicBlock* block = body[bi]; @@ -7255,10 +7321,11 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) ins->mExpensive = false; if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE) hasCall = true; + else if (ins->mCode == IC_PUSH_FRAME) + hasFrame = true; } } - for (int bi = 0; bi < path.Size(); bi++) { InterCodeBasicBlock* block = path[bi]; @@ -7270,6 +7337,10 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) if (!IsMoveable(ins->mCode)) ins->mInvariant = false; + else if (ins->mCode == IC_CONSTANT && ins->mDst.mType == IT_POINTER && ins->mConst.mMemory == IM_FRAME && hasFrame) + ins->mInvariant = false; + else if (ins->mCode == IC_LEA && ins->mSrc[1].mMemory == IM_FRAME && hasFrame) + ins->mInvariant = false; else if (ins->mCode == IC_LOAD) { if (ins->mSrc[0].mTemp >= 0 || ins->mVolatile) @@ -7305,6 +7376,10 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) ins->mInvariant = false; } } + else if (sins->mCode == IC_COPY) + { + ins->mInvariant = false; + } } } } @@ -7572,13 +7647,23 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa GrowingArray tvalues(nullptr); GrowingArray nassigns(0); + int frameLevel = 0; for (int i = 0; i < mInstructions.Size(); i++) { InterInstruction* ins = mInstructions[i]; ins->mInvariant = true; + if (ins->mCode == IC_PUSH_FRAME) + frameLevel++; + else if (ins->mCode == IC_POP_FRAME) + frameLevel--; + if (!IsMoveable(ins->mCode)) ins->mInvariant = false; + else if (ins->mCode == IC_CONSTANT && ins->mDst.mType == IT_POINTER && ins->mConst.mMemory == IM_FRAME && frameLevel != 0) + ins->mInvariant = false; + else if (ins->mCode == IC_LEA && ins->mSrc[1].mMemory == IM_FRAME && frameLevel != 0) + ins->mInvariant = false; else if (ins->mCode == IC_LOAD) { if (ins->mSrc[0].mTemp >= 0 || ins->mVolatile) @@ -7627,6 +7712,10 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa ins->mInvariant = false; } } + else if (sins->mCode == IC_COPY) + { + ins->mInvariant = false; + } } } } @@ -9094,6 +9183,7 @@ void InterCodeProcedure::Close(void) int vi = simpleLocals.Element(i); if (!complexLocals[vi]) { + mLocalVars[vi]->mTemp = true; ResetVisited(); mEntryBlock->SimpleLocalToTemp(vi, AddTemporary(localTypes[vi])); } @@ -9122,6 +9212,7 @@ void InterCodeProcedure::Close(void) TempForwarding(); } + BuildLoopPrefix(); DisassembleDebug("added dominators"); @@ -9366,6 +9457,28 @@ void InterCodeProcedure::Close(void) #endif +#if 1 + ResetVisited(); + if (mEntryBlock->CheckStaticStack()) + { + mLinkerObject->mFlags |= LOBJF_STATIC_STACK; + mLinkerObject->mStackSection = mModule->mLinker->AddSection(mIdent, LST_STATIC_STACK); + + for (int i = 0; i < mLocalVars.Size(); i++) + { + InterVariable* var(mLocalVars[i]); + if (var && !var->mTemp && !var->mLinkerObject) + { + var->mLinkerObject = mModule->mLinker->AddObject(mLocation, var->mIdent, mLinkerObject->mStackSection, LOT_BSS); + var->mLinkerObject->AddSpace(var->mSize); + } + } + + ResetVisited(); + mEntryBlock->CollectStaticStack(mLinkerObject, mLocalVars); + } +#endif + MapVariables(); DisassembleDebug("mapped variabled"); @@ -9379,6 +9492,7 @@ void InterCodeProcedure::Close(void) MergeBasicBlocks(); BuildTraces(false); DisassembleDebug("Merged basic blocks"); + } void InterCodeProcedure::AddCalledFunction(InterCodeProcedure* proc) @@ -9412,7 +9526,7 @@ void InterCodeProcedure::MapVariables(void) mLocalSize = 0; for (int i = 0; i < mLocalVars.Size(); i++) { - if (mLocalVars[i] && mLocalVars[i]->mUsed) + if (mLocalVars[i] && mLocalVars[i]->mUsed && !mLocalVars[i]->mLinkerObject) { mLocalVars[i]->mOffset = mLocalSize; mLocalSize += mLocalVars[i]->mSize; @@ -9765,8 +9879,8 @@ void InterCodeProcedure::Disassemble(const char* name, bool dumpSets) #endif } -InterCodeModule::InterCodeModule(void) - : mGlobalVars(nullptr), mProcedures(nullptr), mCompilerOptions(0) +InterCodeModule::InterCodeModule(Linker * linker) + : mLinker(linker), mGlobalVars(nullptr), mProcedures(nullptr), mCompilerOptions(0) { } diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index aa098e6..de5a6da 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -223,14 +223,14 @@ class InterVariable { public: Location mLocation; - bool mUsed, mAliased; + bool mUsed, mAliased, mTemp; int mIndex, mSize, mOffset, mAddr; int mNumReferences; const Ident * mIdent; LinkerObject * mLinkerObject; InterVariable(void) - : mUsed(false), mAliased(false), mIndex(-1), mSize(0), mOffset(0), mIdent(nullptr), mLinkerObject(nullptr) + : mUsed(false), mAliased(false), mTemp(false), mIndex(-1), mSize(0), mOffset(0), mIdent(nullptr), mLinkerObject(nullptr) { } }; @@ -460,6 +460,9 @@ public: bool OptimizeIntervalCompare(void); bool DropUnreachable(void); + + bool CheckStaticStack(void); + void CollectStaticStack(LinkerObject * lobj, const GrowingVariableArray& localVars); }; class InterCodeModule; @@ -533,7 +536,7 @@ protected: class InterCodeModule { public: - InterCodeModule(void); + InterCodeModule(Linker * linker); ~InterCodeModule(void); bool Disassemble(const char* name); @@ -542,6 +545,8 @@ public: GrowingVariableArray mGlobalVars; + Linker * mLinker; + uint64 mCompilerOptions; }; diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index bdb784a..e038f79 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -8,11 +8,11 @@ LinkerRegion::LinkerRegion(void) {} LinkerSection::LinkerSection(void) - : mObjects(nullptr) + : mObjects(nullptr), mSections(nullptr) {} LinkerObject::LinkerObject(void) - : mReferences(nullptr), mNumTemporaries(0), mSize(0), mAlignment(1) + : mReferences(nullptr), mNumTemporaries(0), mSize(0), mAlignment(1), mStackSection(nullptr) {} LinkerObject::~LinkerObject(void) @@ -235,6 +235,42 @@ bool LinkerRegion::Allocate(LinkerObject* lobj) return false; } +void LinkerRegion::PlaceStackSection(LinkerSection* stackSection, LinkerSection* section) +{ + if (!section->mEnd) + { + int start = stackSection->mEnd; + + for(int i=0; imSections.Size(); i++) + { + PlaceStackSection(stackSection, section->mSections[i]); + if (section->mSections[i]->mStart < start) + start = section->mSections[i]->mStart; + } + + section->mStart = start; + section->mEnd = start; + + for (int i = 0; i < section->mObjects.Size(); i++) + { + LinkerObject* lobj = section->mObjects[i]; + if (lobj->mFlags & LOBJF_REFERENCED) + { + section->mStart -= lobj->mSize; + section->mSize += lobj->mSize; + + lobj->mFlags |= LOBJF_PLACED; + lobj->mAddress = section->mStart; + lobj->mRefAddress = section->mStart + mReloc; + lobj->mRegion = this; + } + } + + if (stackSection->mStart > section->mStart) + stackSection->mStart = section->mStart; + } +} + void Linker::Link(void) { if (mErrors->mErrorCount == 0) @@ -304,10 +340,15 @@ void Linker::Link(void) LinkerSection* lsec = lrgn->mSections[j]; if (lsec->mType == LST_STACK) - { - lsec->mStart = lrgn->mEnd - lsec->mSize; - lsec->mEnd = lrgn->mEnd; - lrgn->mEnd = lsec->mStart; + { + lsec->mStart = lsec->mEnd = lrgn->mEnd; + lrgn->mEnd = lsec->mStart - lsec->mSize; + + for(int i=0; imSections.Size(); i++) + lrgn->PlaceStackSection(lsec, lsec->mSections[i]); + + lsec->mEnd = lsec->mStart; + lsec->mStart = lrgn->mEnd; } } } @@ -440,7 +481,8 @@ static const char* LinkerSectionTypeNames[] = { "DATA", "BSS", "HEAP", - "STACK" + "STACK", + "SSTACK" }; bool Linker::WriteBinFile(const char* filename) diff --git a/oscar64/Linker.h b/oscar64/Linker.h index 32d894b..2c30e3c 100644 --- a/oscar64/Linker.h +++ b/oscar64/Linker.h @@ -30,7 +30,9 @@ enum LinkerSectionType LST_DATA, LST_BSS, LST_HEAP, - LST_STACK + LST_STACK, + LST_STATIC_STACK + }; struct ZeroPageSet @@ -90,6 +92,7 @@ public: GrowingArray mFreeChunks; bool Allocate(LinkerObject* obj); + void PlaceStackSection(LinkerSection* stackSection, LinkerSection* section); }; static const uint32 LREF_LOWBYTE = 0x00000001; @@ -111,7 +114,7 @@ public: const Ident* mIdent; GrowingArray mObjects; - + GrowingArray mSections; int mStart, mEnd, mSize; LinkerSectionType mType; @@ -119,31 +122,32 @@ public: LinkerSection(void); }; -static const uint32 LOBJF_REFERENCED = 0x00000001; -static const uint32 LOBJF_PLACED = 0x00000002; -static const uint32 LOBJF_NO_FRAME = 0x00000004; -static const uint32 LOBJF_INLINE = 0x00000008; -static const uint32 LOBJF_CONST = 0x00000010; -static const uint32 LOBJF_RELEVANT = 0x00000020; - +static const uint32 LOBJF_REFERENCED = 0x00000001; +static const uint32 LOBJF_PLACED = 0x00000002; +static const uint32 LOBJF_NO_FRAME = 0x00000004; +static const uint32 LOBJF_INLINE = 0x00000008; +static const uint32 LOBJF_CONST = 0x00000010; +static const uint32 LOBJF_RELEVANT = 0x00000020; +static const uint32 LOBJF_STATIC_STACK = 0x00000040; class LinkerObject { public: - Location mLocation; - const Ident * mIdent; - LinkerObjectType mType; - int mID; - int mAddress, mRefAddress; - int mSize, mAlignment; - LinkerSection * mSection; - LinkerRegion * mRegion; - uint8 * mData; - InterCodeProcedure* mProc; - uint32 mFlags; - uint8 mTemporaries[16], mTempSizes[16]; - int mNumTemporaries; - ZeroPageSet mZeroPageSet; + Location mLocation; + const Ident * mIdent; + LinkerObjectType mType; + int mID; + int mAddress, mRefAddress; + int mSize, mAlignment; + LinkerSection * mSection; + LinkerRegion * mRegion; + uint8 * mData; + InterCodeProcedure * mProc; + uint32 mFlags; + uint8 mTemporaries[16], mTempSizes[16]; + int mNumTemporaries; + ZeroPageSet mZeroPageSet; + LinkerSection * mStackSection; LinkerObject(void); ~LinkerObject(void); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 22123a8..18d6160 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -12135,6 +12135,7 @@ bool NativeCodeBasicBlock::MoveLoadStoreUp(int at) } mIns[j - 1].mLive |= LIVE_CPU_REG_A; mIns[j] = mIns[at + 1]; + mIns[j].mLive |= LIVE_CPU_REG_A; mIns[at + 1].mType = ASMIT_NOP; mIns[at + 1].mMode = ASMIM_IMPLIED; return true; diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 02c59dc..11784e7 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -73,7 +73,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.4.101"); + strcpy(strProductVersion, "1.5.102"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 6dfdf34..d253a70 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,4,101,0 - PRODUCTVERSION 1,4,101,0 + FILEVERSION 1,5,102,0 + PRODUCTVERSION 1,5,102,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.4.101.0" + VALUE "FileVersion", "1.5.102.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.4.101.0" + VALUE "ProductVersion", "1.5.102.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 1e4e474..c55bc9d 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -3945,15 +3945,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{015F3702-7631-43CC-8735-41950474E793}" - "PackageCode" = "8:{7D690EF3-EE02-4845-BCF6-64CB0E42ED95}" + "ProductCode" = "8:{6DCF4711-61FA-455B-87CE-A5383B7EEB4E}" + "PackageCode" = "8:{20057AF4-DA5C-4190-B17D-094F83470BE1}" "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.4.101" + "ProductVersion" = "8:1.5.102" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:"