Recursive variadic templates

This commit is contained in:
drmortalwombat 2023-09-17 10:24:28 +02:00
parent 935a38607b
commit 06ebf85d9d
16 changed files with 864 additions and 102 deletions

View File

@ -158,6 +158,7 @@ public:
void pop_back(void)
{
_size--;
_data[_size].~T();
}
void insert(int at, const T & t);

View File

@ -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))
{

View File

@ -27,6 +27,7 @@ public:
GlobalAnalyzer* mGlobalAnalyzer;
GrowingArray<ByteCodeProcedure*> mByteCodeFunctions;
ExpandingArray<NativeCodeProcedure*> mNativeProcedures;
TargetMachine mTargetMachine;
uint64 mCompilerOptions;

View File

@ -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
{

View File

@ -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;
}

View File

@ -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;

View File

@ -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,

View File

@ -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();

View File

@ -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;

View File

@ -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)

View File

@ -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<NativeCodeBasicBlock*> 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<uint8> 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;
}

View File

@ -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<Runtime> mRuntime;
ExpandingArray<MulTable> 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);
};

View File

@ -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)
{

View File

@ -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);

View File

@ -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();

View File

@ -164,6 +164,7 @@ enum Token
TK_TEMPLATE,
TK_FRIEND,
TK_CONSTEXPR,
TK_TYPENAME,
NUM_TOKENS
};