diff --git a/include/opp/vector.h b/include/opp/vector.h index 30c8013..417e122 100644 --- a/include/opp/vector.h +++ b/include/opp/vector.h @@ -158,6 +158,7 @@ public: void pop_back(void) { _size--; + _data[_size].~T(); } void insert(int at, const T & t); diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index a0d9cb7..baae398 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -463,6 +463,7 @@ void Compiler::CompileProcedure(InterCodeProcedure* proc) printf("Generate native code <%s>\n", proc->mIdent->mString); ncproc->Compile(proc); + mNativeProcedures.Push(ncproc); } else { @@ -983,6 +984,15 @@ bool Compiler::GenerateCode(void) mCompilationUnits->mSectionStack->mSections.Push(proc->mLinkerObject->mStackSection); } + mNativeCodeGenerator->BuildFunctionProxies(); + + for (int i = 0; i < mNativeProcedures.Size(); i++) + { + if (mCompilerOptions & COPT_VERBOSE2) + printf("Assemble native code <%s>\n", mNativeProcedures[i]->mInterProc->mIdent->mString); + mNativeProcedures[i]->Assemble(); + } + LinkerObject* byteCodeObject = nullptr; if (!(mCompilerOptions & COPT_NATIVE)) { diff --git a/oscar64/Compiler.h b/oscar64/Compiler.h index 632b1fb..3b9f00d 100644 --- a/oscar64/Compiler.h +++ b/oscar64/Compiler.h @@ -27,6 +27,7 @@ public: GlobalAnalyzer* mGlobalAnalyzer; GrowingArray mByteCodeFunctions; + ExpandingArray mNativeProcedures; TargetMachine mTargetMachine; uint64 mCompilerOptions; diff --git a/oscar64/CompilerTypes.h b/oscar64/CompilerTypes.h index 5d0d66f..e6c6016 100644 --- a/oscar64/CompilerTypes.h +++ b/oscar64/CompilerTypes.h @@ -12,6 +12,7 @@ static const uint64 COPT_OPTIMIZE_AUTO_UNROLL = 1ULL << 6; static const uint64 COPT_OPTIMIZE_CONST_EXPRESSIONS = 1ULL << 7; static const uint64 COPT_OPTIMIZE_AUTO_ZEROPAGE = 1ULL << 8; static const uint64 COPT_OPTIMIZE_CONST_PARAMS = 1ULL << 9; +static const uint64 COPT_OPTIMIZE_MERGE_CALLS = 1ULL << 10; static const uint64 COPT_OPTIMIZE_CODE_SIZE = 1ULL << 16; static const uint64 COPT_NATIVE = 1ULL << 17; @@ -43,11 +44,11 @@ static const uint64 COPT_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | static const uint64 COPT_OPTIMIZE_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS; -static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE | COPT_OPTIMIZE_CONST_PARAMS; +static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS; -static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_CONST_PARAMS; +static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS; -static const uint64 COPT_OPTIMIZE_ALL = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_AUTO_ZEROPAGE | COPT_OPTIMIZE_CONST_PARAMS; +static const uint64 COPT_OPTIMIZE_ALL = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_AUTO_ZEROPAGE | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS; enum TargetMachine { diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 850aeff..8c3690b 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -300,6 +300,9 @@ void Expression::Dump(int ident) const case EX_RESULT: printf("RESULT"); break; + case EX_PACK: + printf("PACK"); + break; } printf("\n"); @@ -884,7 +887,7 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio Declaration::Declaration(const Location& loc, DecType type) : mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr), mMangleIdent(nullptr), mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), mNumVars(0), - mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), + mBase(nullptr), mParams(nullptr), mParamPack(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), mConst(nullptr), mMutable(nullptr), mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mMoveConstructor(nullptr), mMoveAssignment(nullptr), mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr), @@ -1076,6 +1079,10 @@ const Ident* Declaration::MangleIdent(void) { mMangleIdent = mBase->MangleIdent()->PreMangle("*"); } + else if (mType == DT_TYPE_ARRAY) + { + mMangleIdent = mBase->MangleIdent()->Mangle("[]"); + } else if (mType == DT_TYPE_STRUCT) { mMangleIdent = mQualIdent->PreMangle("struct "); @@ -1109,6 +1116,30 @@ const Ident* Declaration::MangleIdent(void) } mMangleIdent = mMangleIdent->Mangle(">"); } + else if (mType == DT_PACK_TYPE) + { + Declaration* dec = mBase; + while (dec) + { + const Ident* id; + if (dec->mBase) + id = dec->mBase->MangleIdent(); + else + id = dec->MangleIdent(); + + if (id) + { + if (mMangleIdent) + mMangleIdent = mMangleIdent->Mangle(id->mString); + else + mMangleIdent = id; + } + + dec = dec->mNext; + if (dec) + mMangleIdent = mMangleIdent->Mangle(","); + } + } else mMangleIdent = mQualIdent; @@ -1192,6 +1223,9 @@ bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec) ptdec = ptdec->mNext; } + Declaration* phead = nullptr, * ptail = nullptr; + int pcnt = 0; + while (pexp) { Expression* ex = pexp; @@ -1205,10 +1239,42 @@ bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec) if (pdec) { - if (!ResolveTemplate(ex->mDecType, pdec->mBase)) - return false; + if (pdec->mType == DT_PACK_ARGUMENT) + { + Declaration* tpdec = ex->mDecType; + if (tpdec->IsReference()) + tpdec = tpdec->mBase; + tpdec = tpdec->Clone(); - pdec = pdec->mNext; + if (ptail) + ptail->mNext = tpdec; + else + phead = tpdec; + ptail = tpdec; + } + else + { + if (!ResolveTemplate(ex->mDecType, pdec->mBase)) + return false; + + pdec = pdec->mNext; + } + } + else + return false; + } + + if (pdec) + { + if (pdec->mType == DT_PACK_ARGUMENT) + { + Declaration* tpdec = new Declaration(pdec->mLocation, DT_PACK_TYPE); + if (pdec->mBase->mType == DT_TYPE_REFERENCE) + tpdec->mIdent = pdec->mBase->mBase->mIdent; + else + tpdec->mIdent = pdec->mBase->mIdent; + tpdec->mBase = phead; + mScope->Insert(tpdec->mIdent, tpdec); } else return false; @@ -1259,13 +1325,17 @@ bool Declaration::CanResolveTemplate(Expression* pexp, Declaration* tdec) if (!ResolveTemplate(ex->mDecType, pdec->mBase)) return false; - pdec = pdec->mNext; + if (pdec->mType != DT_PACK_ARGUMENT) + pdec = pdec->mNext; } else return false; } - return true; + if (pdec) + return pdec->mType == DT_PACK_ARGUMENT; + else + return true; } bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) @@ -1341,6 +1411,10 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) return true; } + else if (tdec->mType == DT_PACK_TEMPLATE) + { + return true; + } else if (tdec->mType == DT_TYPE_STRUCT && fdec->mType == DT_TYPE_STRUCT && tdec->mTemplate) { Declaration *ftdec = tdec->mTemplate; @@ -1387,6 +1461,7 @@ Declaration* Declaration::Clone(void) ndec->mFlags = mFlags; ndec->mScope = mScope; ndec->mParams = mParams; + ndec->mParamPack = mParamPack; ndec->mIdent = mIdent; ndec->mQualIdent = mQualIdent; ndec->mValue = mValue; @@ -1400,6 +1475,7 @@ Declaration* Declaration::Clone(void) ndec->mMinValue = mMinValue; ndec->mMaxValue = mMaxValue; ndec->mCompilerOptions = mCompilerOptions; + ndec->mParser = mParser; return ndec; } @@ -1913,6 +1989,8 @@ bool Declaration::IsTemplateSame(const Declaration* dec, const Declaration * tde if (dec->mType == DT_TYPE_TEMPLATE) { dec = tdec->mScope->Lookup(dec->mIdent); + if (!dec) + return true; dflags |= dec->mFlags; } diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index e22d2ce..757e75e 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -41,6 +41,11 @@ enum DecType DT_CONST_CONSTRUCTOR, DT_CONST_TEMPLATE, + DT_PACK_TEMPLATE, + DT_PACK_VARIABLE, + DT_PACK_ARGUMENT, + DT_PACK_TYPE, + DT_VARIABLE, DT_ARGUMENT, DT_ELEMENT, @@ -216,7 +221,8 @@ enum ExpressionType EX_BANKOF, EX_CONSTRUCT, EX_CLEANUP, - EX_RESULT + EX_RESULT, + EX_PACK }; class Expression @@ -254,7 +260,7 @@ public: Location mLocation, mEndLocation; DecType mType; Token mToken; - Declaration * mBase, * mParams, * mNext, * mPrev, * mConst, * mMutable; + Declaration * mBase, * mParams, * mParamPack, * mNext, * mPrev, * mConst, * mMutable; Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment, * mMoveConstructor, * mMoveAssignment; Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment; Declaration * mVTable, * mClass, * mTemplate; diff --git a/oscar64/Errors.h b/oscar64/Errors.h index c2d4b5c..7505713 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -85,6 +85,7 @@ enum ErrorID EERR_FUNCTION_TEMPLATE, EERR_INVALID_BITFIELD, EERR_INVALID_CAPTURE, + EERR_INVALID_PACK_USAGE, EERR_INVALID_CONSTEXPR, EERR_DOUBLE_FREE, diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 0cfc4e0..bfcd4a7 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -4315,10 +4315,12 @@ void InterOperand::Disassemble(FILE* file, InterCodeProcedure* proc) } else if (mMemory == IM_PROCEDURE) { - if (mLinkerObject && mLinkerObject->mIdent) + if (proc->mModule->mProcedures[mVarIndex]) + vname = proc->mModule->mProcedures[mVarIndex]->mIdent->mString; + else if (mLinkerObject && mLinkerObject->mIdent) vname = mLinkerObject->mIdent->mString; } - else if (mMemory == IM_GLOBAL || mMemory == IM_PROCEDURE) + else if (mMemory == IM_GLOBAL) { if (mVarIndex < 0) vname = ""; @@ -4495,6 +4497,24 @@ void InterInstruction::Disassemble(FILE* file, InterCodeProcedure* proc) else vname = proc->mLocalVars[mConst.mVarIndex]->mIdent->mString; } + else if (mConst.mMemory == IM_PROCEDURE) + { + if (proc->mModule->mProcedures[mConst.mVarIndex]) + vname = proc->mModule->mProcedures[mConst.mVarIndex]->mIdent->mString; + else if (mConst.mLinkerObject && mConst.mLinkerObject->mIdent) + vname = mConst.mLinkerObject->mIdent->mString; + } + else if (mConst.mMemory == IM_GLOBAL) + { + if (mConst.mVarIndex < 0) + vname = ""; + else if (!proc->mModule->mGlobalVars[mConst.mVarIndex]) + vname = "null"; + else if (!proc->mModule->mGlobalVars[mConst.mVarIndex]->mIdent) + vname = ""; + else + vname = proc->mModule->mGlobalVars[mConst.mVarIndex]->mIdent->mString; + } fprintf(file, "C%c%d(%d:%d '%s')", memchars[mConst.mMemory], mConst.mOperandSize, mConst.mVarIndex, int(mConst.mIntConst), vname); } @@ -15876,6 +15896,26 @@ void InterCodeBasicBlock::CollectGlobalReferences(NumberSet& referencedGlobals, else globalsChecked = false; break; + case IC_DISPATCH: + { + for (int j = 0; j < mProc->mCalledFunctions.Size(); j++) + { + InterCodeProcedure* proc = mProc->mCalledFunctions[j]; + + if (proc->mGlobalsChecked) + { + if (proc->mStoresIndirect) + storesIndirect = true; + if (proc->mLoadsIndirect) + loadsIndirect = true; + referencedGlobals |= proc->mReferencedGlobals; + modifiedGlobals |= proc->mModifiedGlobals; + } + else + globalsChecked = false; + } + } + break; } } @@ -16237,7 +16277,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l mValueForwardingTable(nullptr), mLocalVars(nullptr), mParamVars(nullptr), mModule(mod), mIdent(ident), mLinkerObject(linkerObject), mNativeProcedure(false), mLeafProcedure(false), mCallsFunctionPointer(false), mCalledFunctions(nullptr), mFastCallProcedure(false), - mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false), + mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false), mAssembled(false), mSaveTempsLinkerObject(nullptr), mValueReturn(false), mFramePointer(false), mCheckUnreachable(true), mReturnType(IT_NONE), mCheapInline(false), mDeclaration(nullptr), mGlobalsChecked(false), mDispatchedCall(false) @@ -17102,7 +17142,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "test"); + CheckFunc = !strcmp(mIdent->mString, "main"); mEntryBlock = mBlocks[0]; @@ -17251,6 +17291,10 @@ void InterCodeProcedure::Close(void) else CollectVariables(paramMemory); + for (int i = 0; i < mLocalVars.Size(); i++) + if (i < mLocalAliasedSet.Size() && mLocalAliasedSet[i]) + mLocalVars[i]->mAliased = true; + BuildDataFlowSets(); ResetVisited(); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 1c8e973..9fcf1eb 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -602,7 +602,7 @@ public: GrowingIntArray mTempOffset, mTempSizes; int mTempSize, mCommonFrameSize, mCallerSavedTemps, mFreeCallerSavedTemps, mFastCallBase; bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode, mFastCallProcedure; - bool mInterrupt, mHardwareInterrupt, mCompiled, mInterruptCalled, mValueReturn, mFramePointer, mDynamicStack; + bool mInterrupt, mHardwareInterrupt, mCompiled, mInterruptCalled, mValueReturn, mFramePointer, mDynamicStack, mAssembled; bool mDispatchedCall; bool mCheckUnreachable; GrowingInterCodeProcedurePtrArray mCalledFunctions; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index f1e7198..36efa32 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1640,6 +1640,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } break; + case EX_PACK: + mErrors->Error(exp->mLocation, EERR_INVALID_PACK_USAGE, "Invalid pack usage"); + return ExValue(TheVoidTypeDeclaration); + case EX_RESULT: { if (lrexp) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 44470aa..a6f8280 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -23308,6 +23308,53 @@ void NativeCodeBasicBlock::PropagateZPAbsolute(void) } } +void NativeCodeBasicBlock::RegisterFunctionCalls(void) +{ + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i < mIns.Size(); i++) + { + if (mIns[i].mType == ASMIT_JSR && mIns[i].mLinkerObject) + mProc->mGenerator->RegisterFunctionCall(this, i); + } + + if (mTrueJump) mTrueJump->RegisterFunctionCalls(); + if (mFalseJump) mFalseJump->RegisterFunctionCalls(); + } +} + +bool NativeCodeBasicBlock::MergeFunctionCalls(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i < mIns.Size(); i++) + { + if (mIns[i].mType == ASMIT_JSR && mIns[i].mLinkerObject) + { + if (mProc->mGenerator->MergeFunctionCall(this, i)) + changed = true; + } + } + + if (changed) + RemoveNops(); + + if (mTrueJump && mTrueJump->MergeFunctionCalls()) + changed = true; + if (mFalseJump && mFalseJump->MergeFunctionCalls()) + changed = true; + } + + return changed; +} + + bool NativeCodeBasicBlock::IsDominatedBy(const NativeCodeBasicBlock* block) const { if (this == block) @@ -41149,11 +41196,12 @@ void NativeCodeProcedure::LoadTempsFromStack(int tempSave) } } + void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "test"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "main"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -41598,15 +41646,32 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) else mExitBlock->mIns.Push(NativeCodeInstruction(mExitBlock->mBranchIns, ASMIT_RTS, ASMIM_IMPLIED)); + + proc->mLinkerObject->mType = LOT_NATIVE_CODE; + + if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS) + { + ResetVisited(); + mEntryBlock->RegisterFunctionCalls(); + } +} + +void NativeCodeProcedure::Assemble(void) +{ + if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS) + { + ResetVisited(); + mEntryBlock->MergeFunctionCalls(); + } + mEntryBlock->Assemble(); + ResetVisited(); mEntryBlock = mEntryBlock->BypassEmptyBlocks(); ResetVisited(); mEntryBlock->ShortcutTailRecursion(); - proc->mLinkerObject->mType = LOT_NATIVE_CODE; - ExpandingArray placement; int total; @@ -41626,7 +41691,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) progress = true; } while (progress); - uint8* data = proc->mLinkerObject->AddSpace(total); + uint8* data = mInterProc->mLinkerObject->AddSpace(total); for (int i = 0; i < placement.Size(); i++) { @@ -41640,7 +41705,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) range.mIdent = Ident::Unique(buffer); range.mOffset = placement[i]->mOffset; range.mSize = placement[i]->mSize; - proc->mLinkerObject->mRanges.Push(range); + mInterProc->mLinkerObject->mRanges.Push(range); placement[i]->CopyCode(this, data); } @@ -41648,10 +41713,10 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) for (int i = 0; i < mRelocations.Size(); i++) { LinkerReference& rl(mRelocations[i]); - rl.mObject = proc->mLinkerObject; + rl.mObject = mInterProc->mLinkerObject; if (!rl.mRefObject) - rl.mRefObject = proc->mLinkerObject; - proc->mLinkerObject->AddReference(rl); + rl.mRefObject = mInterProc->mLinkerObject; + mInterProc->mLinkerObject->AddReference(rl); } if (mGenerator->mCompilerOptions & COPT_DEBUGINFO) @@ -41672,12 +41737,11 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) } mCodeLocations.SetSize(j + 1); - proc->mLinkerObject->AddLocations(mCodeLocations); + mInterProc->mLinkerObject->AddLocations(mCodeLocations); } } } - bool NativeCodeProcedure::MapFastParamsToTemps(void) { NumberSet used(256), modified(256), statics(256), pairs(256); @@ -41926,7 +41990,6 @@ void NativeCodeProcedure::Optimize(void) changed = true; #endif - if (step == 2) { ResetVisited(); @@ -43149,7 +43212,7 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode NativeCodeGenerator::NativeCodeGenerator(Errors* errors, Linker* linker, LinkerSection* runtimeSection) - : mErrors(errors), mLinker(linker), mRuntimeSection(runtimeSection), mCompilerOptions(COPT_DEFAULT) + : mErrors(errors), mLinker(linker), mRuntimeSection(runtimeSection), mCompilerOptions(COPT_DEFAULT), mFunctionCalls(nullptr) { } @@ -43257,6 +43320,242 @@ NativeCodeGenerator::Runtime& NativeCodeGenerator::ResolveRuntime(const Ident* i return mRuntime[i]; } +void NativeCodeGenerator::RegisterFunctionCall(NativeCodeBasicBlock* block, int at) +{ + LinkerObject* lo = block->mIns[at].mLinkerObject; + if (lo->mIdent && !(block->mIns[at].mFlags & NCIF_USE_ZP_32_X)) + { + int i = at; + while (i >= 2 && + block->mIns[i - 1].mType == ASMIT_STA && block->mIns[i - 1].mMode == ASMIM_ZERO_PAGE && + block->mIns[i - 1].mAddress >= BC_REG_FPARAMS && block->mIns[i - 1].mAddress < BC_REG_FPARAMS_END && + block->mIns[i - 2].mType == ASMIT_LDA && (block->mIns[i - 2].mMode == ASMIM_IMMEDIATE || block->mIns[i - 2].mMode == ASMIM_IMMEDIATE_ADDRESS || block->mIns[i - 2].mMode == ASMIM_ZERO_PAGE)) + { + i -= 2; + } + + if (i < at) + { + FunctionCall* ncp = new FunctionCall(); + ncp->mLinkerObject = lo; + ncp->mProxyObject = nullptr; + ncp->mCount = 1; + while (i < at) + { + ncp->mIns[block->mIns[i + 1].mAddress - BC_REG_FPARAMS] = block->mIns[i]; + i += 2; + } + + FunctionCall* cp = mFunctionCalls; + while (cp && cp->mLinkerObject != ncp->mLinkerObject) + cp = cp->mNext; + if (!cp) + { + ncp->mNext = mFunctionCalls; + mFunctionCalls = ncp; + ncp->mSame = nullptr; + } + else + { + FunctionCall* scp = cp; + while (scp && !scp->IsSame(ncp)) + scp = scp->mSame; + if (!scp) + { + ncp->mSame = cp->mSame; + cp->mSame = ncp; + } + else + { + scp->mCount++; + ncp = scp; + } + } + } + } + +} + +bool NativeCodeGenerator::MergeFunctionCall(NativeCodeBasicBlock* block, int at) +{ + LinkerObject* lo = block->mIns[at].mLinkerObject; + if (lo->mIdent) + { + int i = at; + while (i >= 2 && + block->mIns[i - 1].mType == ASMIT_STA && block->mIns[i - 1].mMode == ASMIM_ZERO_PAGE && + block->mIns[i - 1].mAddress >= BC_REG_FPARAMS && block->mIns[i - 1].mAddress < BC_REG_FPARAMS_END && + block->mIns[i - 2].mType == ASMIT_LDA && (block->mIns[i - 2].mMode == ASMIM_IMMEDIATE || block->mIns[i - 2].mMode == ASMIM_IMMEDIATE_ADDRESS || block->mIns[i - 2].mMode == ASMIM_ZERO_PAGE || block->mIns[i - 2].mMode == ASMIM_ABSOLUTE)) + { + i -= 2; + } + + if (i < at) + { + FunctionCall ncp; + ncp.mLinkerObject = lo; + int j = i; + while (i < at) + { + ncp.mIns[block->mIns[i + 1].mAddress - BC_REG_FPARAMS] = block->mIns[i]; + i += 2; + } + + FunctionCall* cp = mFunctionCalls; + while (cp && cp->mLinkerObject != ncp.mLinkerObject) + cp = cp->mNext; + if (cp) + { + FunctionCall* bcp = nullptr; + int bmatch = 0; + + FunctionCall* scp = cp; + while (scp) + { + if (scp->mProxyObject) + { + int m = ncp.Matches(scp); + if (m > bmatch) + { + bmatch = m; + bcp = scp; + } + } + scp = scp->mSame; + } + + if (bcp) + { + while (j < at) + { + if (bcp->mIns[block->mIns[j + 1].mAddress - BC_REG_FPARAMS].mType != ASMIT_INV) + { + block->mIns[j + 0].mType = ASMIT_NOP; block->mIns[j + 0].mMode = ASMIM_IMPLIED; + block->mIns[j + 1].mType = ASMIT_NOP; block->mIns[j + 1].mMode = ASMIM_IMPLIED; + } + j += 2; + } + block->mIns[j].mLinkerObject = bcp->mProxyObject; + return true; + } + } + } + } + return false; +} + +void NativeCodeGenerator::BuildFunctionProxies(void) +{ + FunctionCall* cp = mFunctionCalls; + while (cp) + { + FunctionCall* ncp = cp; + while (ncp) + { + if (ncp->mCount > 1) + { + printf("RFC %s : %d\n", ncp->mLinkerObject->mIdent->mString, ncp->mCount); + ncp->mProxyObject = mLinker->AddObject(ncp->mLinkerObject->mLocation, ncp->mLinkerObject->mIdent->Mangle("@proxy"), ncp->mLinkerObject->mSection, ncp->mLinkerObject->mType); + + ExpandingArray code; + for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++) + { + NativeCodeInstruction& ins(ncp->mIns[i - BC_REG_FPARAMS]); + if (ins.mType == ASMIT_LDA) + { + switch (ins.mMode) + { + case ASMIM_IMMEDIATE: + code.Push(uint8(AsmInsOpcodes[ASMIT_LDA][ASMIM_IMMEDIATE])); + code.Push(uint8(ins.mAddress)); + break; + case ASMIM_ZERO_PAGE: + code.Push(uint8(AsmInsOpcodes[ASMIT_LDA][ASMIM_ZERO_PAGE])); + if (ins.mLinkerObject) + { + LinkerReference rl; + rl.mObject = ncp->mProxyObject; + rl.mOffset = code.Size(); + + rl.mRefObject = ins.mLinkerObject; + rl.mRefOffset = ins.mAddress; + rl.mFlags = LREF_LOWBYTE; + + ncp->mProxyObject->AddReference(rl); + code.Push(0); + } + else + code.Push(uint8(ins.mAddress)); + break; + case ASMIM_IMMEDIATE_ADDRESS: + code.Push(uint8(AsmInsOpcodes[ASMIT_LDA][ASMIM_IMMEDIATE])); + if (ins.mLinkerObject) + { + LinkerReference rl; + rl.mObject = ncp->mProxyObject; + rl.mOffset = code.Size(); + rl.mFlags = 0; + if (ins.mFlags & NCIF_LOWER) + rl.mFlags |= LREF_LOWBYTE; + if (ins.mFlags & NCIF_UPPER) + rl.mFlags |= LREF_HIGHBYTE; + rl.mRefObject = ins.mLinkerObject; + rl.mRefOffset = ins.mAddress; + + ins.mLinkerObject->mFlags |= LOBJF_NO_CROSS; + + ncp->mProxyObject->AddReference(rl); + code.Push(0); + } + else + code.Push(uint8(ins.mAddress)); + break; + case ASMIM_ABSOLUTE: + code.Push(uint8(AsmInsOpcodes[ASMIT_LDA][ASMIM_ABSOLUTE])); + if (ins.mLinkerObject) + { + LinkerReference rl; + rl.mObject = ncp->mProxyObject; + rl.mOffset = code.Size(); + rl.mRefObject = ins.mLinkerObject; + rl.mRefOffset = ins.mAddress; + rl.mFlags = LREF_LOWBYTE | LREF_HIGHBYTE; + ncp->mProxyObject->AddReference(rl); + code.Push(0); + code.Push(0); + } + else + { + code.Push(uint8(ins.mAddress & 0xff)); + code.Push(uint8(ins.mAddress >> 8)); + } + break; + } + code.Push(uint8(AsmInsOpcodes[ASMIT_STA][ASMIM_ZERO_PAGE])); + code.Push(uint8(i)); + } + } + code.Push(uint8(AsmInsOpcodes[ASMIT_JMP][ASMIM_ABSOLUTE])); + + LinkerReference rl; + rl.mObject = ncp->mProxyObject; + rl.mOffset = code.Size(); + rl.mRefObject = ncp->mLinkerObject; + rl.mRefOffset = 0; + rl.mFlags = LREF_LOWBYTE | LREF_HIGHBYTE; + ncp->mProxyObject->AddReference(rl); + code.Push(0); + code.Push(0); + + ncp->mProxyObject->AddData(&(code[0]), code.Size()); + } + ncp = ncp->mSame; + } + cp = cp->mNext; + } +} + + void NativeCodeGenerator::RegisterRuntime(const Ident* ident, LinkerObject* object, int offset) { Runtime rt; @@ -43265,3 +43564,29 @@ void NativeCodeGenerator::RegisterRuntime(const Ident* ident, LinkerObject* obje rt.mOffset = offset; mRuntime.Push(rt); } + +bool NativeCodeGenerator::FunctionCall::IsSame(const FunctionCall* fc) const +{ + for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++) + if (!mIns[i - BC_REG_FPARAMS].IsSame(fc->mIns[i - BC_REG_FPARAMS])) + return false; + return true; +} + +int NativeCodeGenerator::FunctionCall::Matches(const FunctionCall* fc) const +{ + int match = 0; + + for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++) + { + if (fc->mIns[i - BC_REG_FPARAMS].mType != ASMIT_INV && mIns[i - BC_REG_FPARAMS].mType != ASMIT_INV) + { + if (!mIns[i - BC_REG_FPARAMS].IsSame(fc->mIns[i - BC_REG_FPARAMS])) + return -1; + match++; + } + } + + return match; +} + diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 9f2b280..eb72c46 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -669,6 +669,9 @@ public: void PropagateZPAbsolute(void); + void RegisterFunctionCalls(void); + bool MergeFunctionCalls(void); + bool IsDominatedBy(const NativeCodeBasicBlock* block) const; void CheckLive(void); @@ -702,6 +705,7 @@ class NativeCodeProcedure void Compile(InterCodeProcedure* proc); void Optimize(void); + void Assemble(void); NativeCodeBasicBlock* CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* block); NativeCodeBasicBlock* AllocateBlock(void); @@ -756,4 +760,21 @@ public: ExpandingArray mRuntime; ExpandingArray mMulTables; + + struct FunctionCall + { + LinkerObject * mLinkerObject, * mProxyObject; + NativeCodeInstruction mIns[64]; + FunctionCall * mNext, * mSame; + int mCount; + + bool IsSame(const FunctionCall* fc) const; + int Matches(const FunctionCall* fc) const; + }; + + FunctionCall* mFunctionCalls; + + void RegisterFunctionCall(NativeCodeBasicBlock* block, int at); + void BuildFunctionProxies(void); + bool MergeFunctionCall(NativeCodeBasicBlock* block, int at); }; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index f68964f..30391e4 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -271,6 +271,10 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio { break; } + else if (ConsumeTokenIf(TK_TEMPLATE)) + { + ParseTemplateDeclaration(pthis); + } else { Declaration* mdec = ParseDeclaration(nullptr, false, false, pthis); @@ -770,40 +774,48 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified, Decl dec = ParseBaseTypeQualify(qualified, dec, pident); - if (dec && dec->mType <= DT_TYPE_FUNCTION) + if (dec) { - if ((flags & ~dec->mFlags) == DTF_CONST) - dec = dec->ToConstType(); - else if (dec->IsSimpleType() && (flags & ~dec->mFlags)) - { - Declaration* ndec = new Declaration(dec->mLocation, dec->mType); - ndec->mFlags = dec->mFlags | flags; - ndec->mSize = dec->mSize; - ndec->mBase = dec->mBase; - dec = ndec; - } - else if (dec->mType == DT_TYPE_STRUCT && (flags & ~dec->mFlags)) + if (dec->mType <= DT_TYPE_FUNCTION) { if ((flags & ~dec->mFlags) == DTF_CONST) dec = dec->ToConstType(); - else + else if (dec->IsSimpleType() && (flags & ~dec->mFlags)) { Declaration* ndec = new Declaration(dec->mLocation, dec->mType); ndec->mFlags = dec->mFlags | flags; ndec->mSize = dec->mSize; ndec->mBase = dec->mBase; - ndec->mScope = dec->mScope; - ndec->mParams = dec->mParams; - ndec->mIdent = dec->mIdent; - ndec->mQualIdent = dec->mQualIdent; dec = ndec; } + else if (dec->mType == DT_TYPE_STRUCT && (flags & ~dec->mFlags)) + { + if ((flags & ~dec->mFlags) == DTF_CONST) + dec = dec->ToConstType(); + else + { + Declaration* ndec = new Declaration(dec->mLocation, dec->mType); + ndec->mFlags = dec->mFlags | flags; + ndec->mSize = dec->mSize; + ndec->mBase = dec->mBase; + ndec->mScope = dec->mScope; + ndec->mParams = dec->mParams; + ndec->mIdent = dec->mIdent; + ndec->mQualIdent = dec->mQualIdent; + dec = ndec; + } + } } + else if (dec->mType == DT_PACK_TEMPLATE || dec->mType == DT_PACK_TYPE) + { + if ((flags & ~dec->mFlags) == DTF_CONST) + dec = dec->ToConstType(); + } + else + mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", dec->mQualIdent); } - else if (!dec) - mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", pident); else - mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", dec->mQualIdent); + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", pident); break; @@ -1014,9 +1026,8 @@ Declaration* Parser::ParsePostfixDeclaration(void) ndec->mBase = dec; return ndec; } - else if (mScanner->mToken == TK_OPEN_PARENTHESIS) + else if (ConsumeTokenIf(TK_OPEN_PARENTHESIS)) { - mScanner->NextToken(); Declaration* vdec = ParsePostfixDeclaration(); if (mScanner->mToken == TK_CLOSE_PARENTHESIS) mScanner->NextToken(); @@ -1024,6 +1035,23 @@ Declaration* Parser::ParsePostfixDeclaration(void) mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "')' expected"); dec = vdec; } + else if (ConsumeTokenIf(TK_ELLIPSIS)) + { + if (mScanner->mToken == TK_IDENT) + { + dec = new Declaration(mScanner->mLocation, DT_PACK_VARIABLE); + dec->mIdent = mScanner->mTokenIdent; + dec->mSection = mBSSection; + dec->mBase = nullptr; + mScanner->NextToken(); + } + else + { + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); + dec = new Declaration(mScanner->mLocation, DT_ANON); + dec->mBase = nullptr; + } + } else if (mScanner->mToken == TK_IDENT) { dec = new Declaration(mScanner->mLocation, DT_VARIABLE); @@ -1041,7 +1069,12 @@ Declaration* Parser::ParsePostfixDeclaration(void) while (!ConsumeTokenIf(TK_GREATER_THAN)) mScanner->NextToken(); - if (mTemplateScope->mName) + if (mTemplateScope->mParent) + { + if (mTemplateScope->mParent->mName) + dec->mIdent = dec->mIdent->Mangle(mTemplateScope->mParent->mName->mString); + } + else if (mTemplateScope->mName) dec->mIdent = dec->mIdent->Mangle(mTemplateScope->mName->mString); } } @@ -1145,31 +1178,94 @@ Declaration * Parser::ParseFunctionDeclaration(Declaration* bdec) if (!(adec->mBase->mFlags & DTF_DEFINED) && adec->mBase->mType != DT_TYPE_ARRAY && !adec->mBase->mTemplate) mErrors->Error(adec->mLocation, EERR_UNDEFINED_OBJECT, "Type of argument not defined"); - adec->mType = DT_ARGUMENT; - adec->mVarIndex = vi; - adec->mOffset = 0; - if (adec->mBase->mType == DT_TYPE_ARRAY) + if (adec->mType == DT_PACK_VARIABLE) { - Declaration* ndec = new Declaration(adec->mBase->mLocation, DT_TYPE_POINTER); - ndec->mBase = adec->mBase->mBase; - ndec->mSize = 2; - ndec->mFlags |= DTF_DEFINED; - adec->mBase = ndec; + adec->mType = DT_PACK_ARGUMENT; + if (adec->mBase) + { + ndec->mParamPack = adec; + + Declaration* atdec = adec->mBase; + + if (atdec->IsReference()) + atdec = atdec->mBase; + if (atdec->mType == DT_PACK_TYPE) + { + atdec = atdec->mBase; + + Declaration* apdec = adec; + while (atdec) + { + apdec = new Declaration(adec->mLocation, DT_ARGUMENT); + if (!adec->mParams) + adec->mParams = apdec; + + if (adec->mBase->IsReference()) + apdec->mBase = atdec->BuildReference(adec->mLocation); + else + apdec->mBase = atdec; + atdec = atdec->mNext; + apdec->mFlags = DTF_DEFINED; + apdec->mVarIndex = vi; + apdec->mOffset = 0; + + if (apdec->mBase->mType == DT_TYPE_ARRAY) + { + Declaration* ndec = new Declaration(apdec->mBase->mLocation, DT_TYPE_POINTER); + ndec->mBase = apdec->mBase->mBase; + ndec->mSize = 2; + ndec->mFlags |= DTF_DEFINED; + apdec->mBase = ndec; + } + + apdec->mSize = apdec->mBase->mSize; + + vi += apdec->mSize; + if (pdec) + pdec->mNext = apdec; + else + ndec->mParams = apdec; + pdec = apdec; + } + } + else + { + if (pdec) + pdec->mNext = adec; + else + ndec->mParams = adec; + pdec = adec; + } + } } - - adec->mSize = adec->mBase->mSize; - - if ((mCompilerOptions & COPT_CPLUSPLUS) && ConsumeTokenIf(TK_ASSIGN)) - { - adec->mValue = ParseExpression(false); - } - - vi += adec->mSize; - if (pdec) - pdec->mNext = adec; else - ndec->mParams = adec; - pdec = adec; + { + adec->mType = DT_ARGUMENT; + adec->mVarIndex = vi; + adec->mOffset = 0; + if (adec->mBase->mType == DT_TYPE_ARRAY) + { + Declaration* ndec = new Declaration(adec->mBase->mLocation, DT_TYPE_POINTER); + ndec->mBase = adec->mBase->mBase; + ndec->mSize = 2; + ndec->mFlags |= DTF_DEFINED; + adec->mBase = ndec; + } + + adec->mSize = adec->mBase->mSize; + + if ((mCompilerOptions & COPT_CPLUSPLUS) && ConsumeTokenIf(TK_ASSIGN)) + { + adec->mValue = ParseExpression(false); + } + + vi += adec->mSize; + if (pdec) + pdec->mNext = adec; + else + ndec->mParams = adec; + pdec = adec; + } if (mScanner->mToken == TK_COMMA) mScanner->NextToken(); @@ -4057,6 +4153,9 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (ldec && ldec != pdec) mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate definition"); } + else if (ptempl && mTemplateScope && pthis) + { + } else if (!pdec) mErrors->Error(ndec->mLocation, EERR_OBJECT_NOT_FOUND, "Object not declarared in scope", ndec->mQualIdent); @@ -4433,7 +4532,7 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec) } else if ((mCompilerOptions & COPT_CPLUSPLUS) && dec->mBase->mDestructor) { - Expression* vexp = new Expression(pdec->mLocation, EX_VARIABLE); + Expression* vexp = new Expression(dec->mLocation, EX_VARIABLE); vexp->mDecType = dec->mBase; vexp->mDecValue = dec; @@ -5203,6 +5302,12 @@ Expression* Parser::ParseSimpleExpression(bool lhs) exp->mDecType = dec->mBase; } } + else if (dec->mType == DT_PACK_ARGUMENT) + { + exp = new Expression(mScanner->mLocation, EX_PACK); + exp->mDecValue = dec; + exp->mDecType = dec->mBase; + } else if (dec->mType <= DT_TYPE_FUNCTION) { if (lhs) @@ -5561,6 +5666,7 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) int dist = 0; + bool packtemp = false; while (pexp) { Expression* ex = pexp; @@ -5579,9 +5685,21 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) if (etype->mType == DT_TYPE_REFERENCE) etype = etype->mBase; - if (ptype->mType == DT_TYPE_TEMPLATE) + if (ptype->mType == DT_PACK_TEMPLATE || ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->mType == DT_PACK_TEMPLATE) + packtemp = true; + + if (ptype->mType == DT_TYPE_TEMPLATE || ptype->mType == DT_PACK_TEMPLATE) { dist += 1; + } + else if (ptype->mType == DT_TYPE_REFERENCE && (ptype->mBase->mType == DT_TYPE_TEMPLATE || ptype->mBase->mType == DT_PACK_TEMPLATE)) + { + if (ex->IsLValue()) + dist += 1; + else if (ptype->mBase->mFlags & DTF_CONST) + dist += 1; + else + return NOOVERLOAD; } else if (ptype->mType == DT_TYPE_INTEGER && etype->mType == DT_TYPE_INTEGER) { @@ -5701,10 +5819,15 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) else return NOOVERLOAD; } + else if (ptype->mType == DT_TYPE_REFERENCE && (ptype->mBase->mFlags & DTF_CONST) && ptype->mBase->CanAssign(etype)) + { + dist += 32; + } else return NOOVERLOAD; - pdec = pdec->mNext; + if (!packtemp) + pdec = pdec->mNext; } else if (fdec->mBase->mFlags & DTF_VARIADIC) { @@ -5721,6 +5844,16 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) pdec = pdec->mNext; } + if (pdec) + { + Declaration* ptype = pdec->mBase; + if (ptype->mType == DT_PACK_TEMPLATE || ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->mType == DT_PACK_TEMPLATE) + packtemp = true; + } + + if (pdec && packtemp) + return dist; + if (pdec) return NOOVERLOAD; @@ -7567,15 +7700,43 @@ Expression* Parser::ParseExpression(bool lhs) return ParseAssignmentExpression(lhs); } +Expression* Parser::ExpandArgumentPack(Expression* exp, Declaration* dec) +{ + Expression* vex = new Expression(exp->mLocation, EX_VARIABLE); + vex->mDecType = dec->mBase; + vex->mDecValue = dec; + + if (dec->mNext) + { + Expression* lex = new Expression(exp->mLocation, EX_LIST); + lex->mToken = TK_COMMA; + lex->mLeft = vex; + lex->mRight = ExpandArgumentPack(exp, dec->mNext); + return lex; + } + else + return vex; +} + Expression* Parser::ParseListExpression(bool lhs) { Expression* exp = ParseExpression(lhs); - if (mScanner->mToken == TK_COMMA) + if (exp->mType == EX_PACK) + { + if (ConsumeTokenIf(TK_ELLIPSIS)) + { + if (exp->mDecValue->mParams) + exp = ExpandArgumentPack(exp, exp->mDecValue->mParams); + else + exp = nullptr; + } + } + + if (ConsumeTokenIf(TK_COMMA)) { Expression* nexp = new Expression(mScanner->mLocation, EX_LIST); - nexp->mToken = mScanner->mToken; + nexp->mToken = TK_COMMA; nexp->mLeft = exp; - mScanner->NextToken(); nexp->mRight = ParseListExpression(false); exp = nexp; } @@ -7607,6 +7768,8 @@ Expression* Parser::ParseFunction(Declaration * dec) scope->Insert(pdec->mIdent, pdec); pdec = pdec->mNext; } + if (dec->mParamPack) + mScope->Insert(dec->mParamPack->mIdent, dec->mParamPack); mLocalIndex = 0; mTempVars = nullptr; @@ -8183,6 +8346,16 @@ Expression* Parser::ParseStatement(void) if (mFunctionType->mBase->mType == DT_TYPE_AUTO) { mFunctionType->mBase = exp->mLeft->mDecType; + if (mFunctionType->mBase->mType == DT_TYPE_STRUCT) + { + // Make room for value struct return + Declaration* p = mFunctionType->mParams; + while (p) + { + p->mVarIndex += 2; + p = p->mNext; + } + } } exp->mLeft = CoerceExpression(exp->mLeft, mFunctionType->mBase); } @@ -8349,15 +8522,50 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp if (expd) { - tdec->mParams = expd->mParams; - Declaration* dec = tdec->mParams; - Declaration* xdec = tmpld->mParams; + if (tmpld->mBase->mType == DT_TEMPLATE) + { + Parser* p = tmpld->mBase->mParser->Clone(); + + p->mScanner->Replay(tmpld->mBase->mTokens); + + tdec = tmpld->mBase->Clone(); + tdec->mScope->mName = expd->mScope->mName; + tdec->mScope->mParent = expd->mScope; + + p->ParseTemplateDeclarationBody(tdec, nullptr); + + return tdec; + } + + Declaration* ppdec = nullptr; + Declaration* dec = expd->mParams; + Declaration* pdec = tmpld->mParams; + while (dec) { - tdec->mScope->Insert(xdec->mIdent, dec->mBase); + Declaration* epdec = dec->Clone(); + + tdec->mScope->Insert(epdec->mIdent, epdec->mBase); + epdec->mFlags |= DTF_DEFINED; + + if (ppdec) + ppdec->mNext = epdec; + else + tdec->mParams = epdec; + ppdec = epdec; + dec = dec->mNext; - xdec = xdec->mNext; + pdec = pdec->mNext; } + + if (pdec) + { + if (ppdec) + ppdec->mNext = pdec; + else + tdec->mParams = pdec; + } + } else { @@ -8438,6 +8646,8 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp while (!tmpld->mTokens) tmpld = tmpld->mNext; + Declaration* pthis = tmpld->mClass; + Declaration* etdec = tmpld->mNext; while (etdec && !etdec->IsSameParams(tdec)) etdec = etdec->mNext; @@ -8464,7 +8674,7 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp return bdec; } - Parser* p = tmpld->mParser; + Parser* p = tmpld->mParser->Clone(); p->mScanner->Replay(tmpld->mTokens); @@ -8472,6 +8682,8 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp tdec->mNext = tmpld->mNext; tmpld->mNext = tdec; + tdec->mScope->mParent = tmpld->mScope->mParent; + p->mTemplateScope = tdec->mScope; if (tmpld->mFlags & DTF_AUTO_TEMPLATE) { @@ -8501,7 +8713,10 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp ndec->mQualIdent = ndec->mQualIdent->Mangle(tdec->mScope->mName->mString); } else - tdec->mBase = p->ParseDeclaration(nullptr, true, false, nullptr, tdec); + { + tdec->mBase = p->ParseDeclaration(nullptr, true, false, tmpld->mClass, tdec); + } + p->mTemplateScope = nullptr; if (tdec->mBase->mType == DT_ANON) @@ -8522,7 +8737,15 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp mpdec = mpdec->mNext; if (mpdec && mpdec->mTemplate) { - p->ParseTemplateExpansion(mpdec->mTemplate, tdec); + if (mdec->mTemplate) + { + Declaration * mtdec = p->ParseTemplateExpansion(mpdec->mTemplate, tdec); + mtdec->mClass = mdec->mTemplate->mClass; + mdec->mTemplate = mtdec; + mdec->mTemplate->mBase = mdec; + } + else + p->ParseTemplateExpansion(mpdec->mTemplate, tdec); } } @@ -8669,21 +8892,33 @@ Declaration* Parser::FunctionAutoParamsToTemplate(Declaration* fdec) return nullptr; } -void Parser::ParseTemplateDeclaration(void) +Declaration * Parser::ParseTemplateDeclaration(Declaration* pthis) { - ConsumeToken(TK_LESS_THAN); Declaration* tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE); tdec->mParser = this->Clone(); - tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); + tdec->mScope = new DeclarationScope(mTemplateScope, SLEVEL_TEMPLATE); + tdec->mClass = pthis; Declaration* ppdec = nullptr; + ConsumeToken(TK_LESS_THAN); for (;;) { Declaration* pdec = nullptr; - if (ConsumeTokenIf(TK_CLASS)) + if (ConsumeTokenIf(TK_CLASS) || ConsumeTokenIf(TK_TYPENAME)) { - if (mScanner->mToken == TK_IDENT) + if (ConsumeTokenIf(TK_ELLIPSIS)) + { + if (mScanner->mToken == TK_IDENT) + { + pdec = new Declaration(mScanner->mLocation, DT_PACK_TEMPLATE); + pdec->mIdent = mScanner->mTokenIdent; + mScanner->NextToken(); + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); + } + else if (mScanner->mToken == TK_IDENT) { pdec = new Declaration(mScanner->mLocation, DT_TYPE_TEMPLATE); pdec->mIdent = mScanner->mTokenIdent; @@ -8724,6 +8959,21 @@ void Parser::ParseTemplateDeclaration(void) ConsumeToken(TK_GREATER_THAN); + if (ConsumeTokenIf(TK_TEMPLATE)) + { + mTemplateScope = tdec->mScope; + tdec->mBase = ParseTemplateDeclaration(pthis); + mTemplateScope = tdec->mScope->mParent; + tdec->mBase->mBase->mTemplate = tdec; + } + else + ParseTemplateDeclarationBody(tdec, pthis); + + return tdec; +} + +void Parser::ParseTemplateDeclarationBody(Declaration * tdec, Declaration * pthis) +{ mScanner->BeginRecord(); if (mScanner->mToken == TK_CLASS) { @@ -8772,10 +9022,13 @@ void Parser::ParseTemplateDeclaration(void) adec = ReverseDeclaration(adec, bdec); - mTemplateScope = nullptr; + mTemplateScope = tdec->mScope->mParent; if (adec->mBase->mType == DT_TYPE_FUNCTION) { + if (pthis) + PrependThisArgument(adec->mBase, pthis); + if (ConsumeTokenIf(TK_CONST)) adec->mBase->mFlags |= DTF_CONST; @@ -8801,6 +9054,18 @@ void Parser::ParseTemplateDeclaration(void) mScanner->NextToken(); } } + else if (ConsumeTokenIf(TK_SEMICOLON)) + { + + } + else + { + mErrors->Error(bdec->mLocation, EERR_FUNCTION_TEMPLATE, "Function template body expected"); + adec->mType = DT_TYPE_VOID; + tdec->mBase = adec; + adec->mIdent = adec->mQualIdent = Ident::Unique("_"); + adec->mTemplate = tdec; + } } else { @@ -10440,7 +10705,7 @@ void Parser::ParseNamespace(void) else if (mScanner->mToken == TK_TEMPLATE) { mScanner->NextToken(); - ParseTemplateDeclaration(); + ParseTemplateDeclaration(nullptr); } else if (mScanner->mToken == TK_NAMESPACE) { @@ -10523,7 +10788,7 @@ void Parser::Parse(void) else if (mScanner->mToken == TK_TEMPLATE) { mScanner->NextToken(); - ParseTemplateDeclaration(); + ParseTemplateDeclaration(nullptr); } else if (mScanner->mToken == TK_NAMESPACE) { diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 13feebf..7e56ab5 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -105,7 +105,8 @@ protected: void CompleteFunctionDefaultParams(Expression* exp); void ExpandFunctionCallTemplate(Expression* exp); - void ParseTemplateDeclaration(void); + Declaration * ParseTemplateDeclaration(Declaration* pthis); + void ParseTemplateDeclarationBody(Declaration* tdec, Declaration* pthis); Declaration* FunctionAutoParamsToTemplate(Declaration* fdec); Declaration* ParseTemplateExpansion(Declaration* tmpld, Declaration* expd); @@ -130,6 +131,8 @@ protected: Expression* ParseAssignmentExpression(bool lhs); Expression* ParseExpression(bool lhs); Expression* ParseRExpression(void); + + Expression* ExpandArgumentPack(Expression * exp, Declaration* dec); Expression* ParseListExpression(bool lhs); Expression* ParseParenthesisExpression(void); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 5b23920..849a06e 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -165,6 +165,7 @@ const char* TokenNames[] = "'template'", "'friend'", "'constexpr'", + "'typename'", }; @@ -482,14 +483,12 @@ void Scanner::NextToken(void) mReplay = mReplay->mNext; } else - { NextPreToken(); - if (mRecord) - { - mRecordLast->mNext = new TokenSequence(this); - mRecordLast = mRecordLast->mNext; - } + if (mRecord) + { + mRecordLast->mNext = new TokenSequence(this); + mRecordLast = mRecordLast->mNext; } } @@ -1520,6 +1519,8 @@ void Scanner::NextRawToken(void) mToken = TK_FRIEND; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "constexpr")) mToken = TK_CONSTEXPR; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "typename")) + mToken = TK_TYPENAME; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator")) { NextRawToken(); diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 3408285..9d6ade7 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -164,6 +164,7 @@ enum Token TK_TEMPLATE, TK_FRIEND, TK_CONSTEXPR, + TK_TYPENAME, NUM_TOKENS };