Recursive variadic templates
This commit is contained in:
parent
935a38607b
commit
06ebf85d9d
|
@ -158,6 +158,7 @@ public:
|
|||
void pop_back(void)
|
||||
{
|
||||
_size--;
|
||||
_data[_size].~T();
|
||||
}
|
||||
|
||||
void insert(int at, const T & t);
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -27,6 +27,7 @@ public:
|
|||
GlobalAnalyzer* mGlobalAnalyzer;
|
||||
|
||||
GrowingArray<ByteCodeProcedure*> mByteCodeFunctions;
|
||||
ExpandingArray<NativeCodeProcedure*> mNativeProcedures;
|
||||
|
||||
TargetMachine mTargetMachine;
|
||||
uint64 mCompilerOptions;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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,10 +5685,22 @@ 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)
|
||||
{
|
||||
if (ptype->mSize == etype->mSize)
|
||||
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -164,6 +164,7 @@ enum Token
|
|||
TK_TEMPLATE,
|
||||
TK_FRIEND,
|
||||
TK_CONSTEXPR,
|
||||
TK_TYPENAME,
|
||||
|
||||
NUM_TOKENS
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue