Merge branch 'drmortalwombat:main' into main

This commit is contained in:
Craig Taylor 2025-04-21 11:53:36 -04:00 committed by GitHub
commit 1e2b227113
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 398 additions and 156 deletions

View File

@ -770,7 +770,10 @@ void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration*
decb = decb->mBase; decb = decb->mBase;
if (decb && decb->mStripe != 1) if (decb && decb->mStripe != 1)
{
AddGlobalVariableRanges(var->mLinkerObject, decb, 0, nullptr); AddGlobalVariableRanges(var->mLinkerObject, decb, 0, nullptr);
var->mLinkerObject->mStripe = decb->mStripe;
}
Declaration* type = dec->mBase; Declaration* type = dec->mBase;
while (type->mType == DT_TYPE_ARRAY) while (type->mType == DT_TYPE_ARRAY)

View File

@ -45,7 +45,7 @@ bool LinkerReference::operator!=(const LinkerReference& ref)
} }
LinkerObject::LinkerObject(void) LinkerObject::LinkerObject(void)
: mReferences(nullptr), mNumTemporaries(0), mSize(0), mAlignment(1), mStackSection(nullptr), mIdent(nullptr), mFullIdent(nullptr), mStartUsed(0x10000), mEndUsed(0x00000), mMemory(nullptr) : mReferences(nullptr), mNumTemporaries(0), mSize(0), mStripe(0), mAlignment(1), mStackSection(nullptr), mIdent(nullptr), mFullIdent(nullptr), mStartUsed(0x10000), mEndUsed(0x00000), mMemory(nullptr)
, mPrefix(nullptr), mSuffix(nullptr), mProc(nullptr), mNativeProc(nullptr) , mPrefix(nullptr), mSuffix(nullptr), mProc(nullptr), mNativeProc(nullptr)
{} {}

View File

@ -190,7 +190,7 @@ public:
LinkerObjectType mType; LinkerObjectType mType;
int mID, mMapID; int mID, mMapID;
int mAddress, mRefAddress; int mAddress, mRefAddress;
int mSize, mAlignment, mStartUsed, mEndUsed; int mSize, mAlignment, mStripe, mStartUsed, mEndUsed;
LinkerSection * mSection; LinkerSection * mSection;
LinkerRegion * mRegion; LinkerRegion * mRegion;
uint8 * mData, * mMemory; uint8 * mData, * mMemory;

View File

@ -32,6 +32,33 @@ static const uint32 LIVE_ALL = 0x000000ff;
static int GlobalValueNumber = 0; static int GlobalValueNumber = 0;
static bool IsPowerOf2(unsigned n)
{
return (n & (n - 1)) == 0;
}
static int Binlog(unsigned n)
{
int k = -1;
while (n)
{
n >>= 1;
k++;
}
return k;
}
static unsigned BinMask(unsigned n)
{
n |= n >> 8;
n |= n >> 4;
n |= n >> 2;
n |= n >> 1;
return n;
}
NativeRegisterData::NativeRegisterData(void) NativeRegisterData::NativeRegisterData(void)
: mMode(NRDM_UNKNOWN), mValue(GlobalValueNumber++), mMask(0) : mMode(NRDM_UNKNOWN), mValue(GlobalValueNumber++), mMask(0)
{ {
@ -1939,6 +1966,23 @@ bool NativeCodeInstruction::MayReference(const NativeCodeInstruction& ins, bool
return false; return false;
} }
bool NativeCodeInstruction::SameLinkerObjectVariableRange(const NativeCodeInstruction& ins, bool sameXY) const
{
if (mLinkerObject == ins.mLinkerObject)
{
if (mMode == ASMIM_ABSOLUTE && ins.mMode == ASMIM_ABSOLUTE)
return mAddress == ins.mAddress;
else if (mMode == ins.mMode && sameXY)
return mAddress == ins.mAddress;
else if (mLinkerObject && mLinkerObject->mStripe > 1)
return mAddress / mLinkerObject->mStripe == ins.mAddress / mLinkerObject->mStripe;
else
return true;
}
else
return false;
}
bool NativeCodeInstruction::MayBeChangedOnAddress(const NativeCodeInstruction& ins, bool sameXY) const bool NativeCodeInstruction::MayBeChangedOnAddress(const NativeCodeInstruction& ins, bool sameXY) const
{ {
if (mMode == ASMIM_IMMEDIATE || mMode == ASMIM_IMMEDIATE_ADDRESS) if (mMode == ASMIM_IMMEDIATE || mMode == ASMIM_IMMEDIATE_ADDRESS)
@ -1974,10 +2018,8 @@ bool NativeCodeInstruction::MayBeChangedOnAddress(const NativeCodeInstruction& i
} }
else if (ins.mMode == ASMIM_ABSOLUTE) else if (ins.mMode == ASMIM_ABSOLUTE)
{ {
if (mMode == ASMIM_ABSOLUTE) if (mMode == ASMIM_ABSOLUTE || mMode == ASMIM_ABSOLUTE_X || mMode == ASMIM_ABSOLUTE_Y)
return mLinkerObject == ins.mLinkerObject && mAddress == ins.mAddress; return SameLinkerObjectVariableRange(ins, sameXY);
else if (mMode == ASMIM_ABSOLUTE_X || mMode == ASMIM_ABSOLUTE_Y)
return mLinkerObject == ins.mLinkerObject;
else if (mMode == ASMIM_INDIRECT_Y || mMode == ASMIM_INDIRECT_X) else if (mMode == ASMIM_INDIRECT_Y || mMode == ASMIM_INDIRECT_X)
return mAddress != BC_REG_STACK; return mAddress != BC_REG_STACK;
else else
@ -1986,12 +2028,7 @@ bool NativeCodeInstruction::MayBeChangedOnAddress(const NativeCodeInstruction& i
else if (ins.mMode == ASMIM_ABSOLUTE_X || ins.mMode == ASMIM_ABSOLUTE_Y) else if (ins.mMode == ASMIM_ABSOLUTE_X || ins.mMode == ASMIM_ABSOLUTE_Y)
{ {
if (mMode == ASMIM_ABSOLUTE || mMode == ASMIM_ABSOLUTE_X || mMode == ASMIM_ABSOLUTE_Y) if (mMode == ASMIM_ABSOLUTE || mMode == ASMIM_ABSOLUTE_X || mMode == ASMIM_ABSOLUTE_Y)
{ return SameLinkerObjectVariableRange(ins, sameXY);
if (mLinkerObject != ins.mLinkerObject)
return false;
else
return mMode != ins.mMode || !sameXY || mAddress == ins.mAddress;
}
else if (mMode == ASMIM_INDIRECT_Y || mMode == ASMIM_INDIRECT_X) else if (mMode == ASMIM_INDIRECT_Y || mMode == ASMIM_INDIRECT_X)
return mAddress != BC_REG_STACK; return mAddress != BC_REG_STACK;
else else
@ -2910,6 +2947,13 @@ bool NativeCodeInstruction::BitFieldForwarding(NativeRegisterDataSet& data, AsmI
data.mRegs[CPU_REG_A].mValue ^= 3; data.mRegs[CPU_REG_A].mValue ^= 3;
changed = true; changed = true;
} }
else if (mMode == ASMIM_IMMEDIATE && mAddress + ((data.mRegs[CPU_REG_A].mValue & data.mRegs[CPU_REG_A].mMask) | (~data.mRegs[CPU_REG_A].mMask & 255)) < 256)
{
data.mRegs[CPU_REG_C].mMask = 1;
data.mRegs[CPU_REG_C].mValue = 0;
data.mRegs[CPU_REG_A].mMask = ~BinMask(mAddress + ((data.mRegs[CPU_REG_A].mValue & data.mRegs[CPU_REG_A].mMask) | (~data.mRegs[CPU_REG_A].mMask & 255))) & 255;
data.mRegs[CPU_REG_A].mValue = 0;
}
else else
{ {
data.mRegs[CPU_REG_C].mMask = 0; data.mRegs[CPU_REG_C].mMask = 0;
@ -9680,32 +9724,6 @@ int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, NativeCodeProc
} }
} }
static bool IsPowerOf2(unsigned n)
{
return (n & (n - 1)) == 0;
}
static int Binlog(unsigned n)
{
int k = -1;
while (n)
{
n >>= 1;
k++;
}
return k;
}
static unsigned BinMask(unsigned n)
{
n |= n >> 8;
n |= n >> 4;
n |= n >> 2;
n |= n >> 1;
return n;
}
void NativeCodeBasicBlock::AddAsrSignedByte(InterCodeProcedure* proc, const InterInstruction* ains, const InterInstruction* sins) void NativeCodeBasicBlock::AddAsrSignedByte(InterCodeProcedure* proc, const InterInstruction* ains, const InterInstruction* sins)
{ {
@ -28610,6 +28628,108 @@ bool NativeCodeBasicBlock::PatchSingleUseGlobalLoad(const NativeCodeBasicBlock*
return changed; return changed;
} }
bool NativeCodeBasicBlock::CheckSingleUseGlobalLoadStruct(const NativeCodeBasicBlock* block, const NativeCodeInstruction& rins, int at, const NativeCodeInstruction& ains, bool cleared, bool poisoned)
{
bool ok = true;
if (!mPatched)
{
if (at == 0)
mPatched = true;
if (this != block && !IsDominatedBy(block))
poisoned = true;
bool used = false;
for (int i = at; i < mIns.Size() && !cleared; i++)
{
const NativeCodeInstruction& ins(mIns[i]);
if (ins.SameEffectiveAddress(rins))
{
if (ins.mType == ASMIT_LDA)
{
if (poisoned)
return false;
used = true;
}
else if (ins.mType == ASMIT_STA || ins.mType == ASMIT_STX || ins.mType == ASMIT_STY)
{
cleared = true;
poisoned = false;
}
else
poisoned = true;
}
else if (poisoned && rins.MayBeSameAddress(ins))
return false;
else if (rins.MayBeChangedOnAddress(ins, true) || ains.MayBeChangedOnAddress(ins, true))
poisoned = true;
else if (ins.ChangesXReg() && ains.ReferencesXReg() || ins.ChangesYReg() && ains.ReferencesYReg())
poisoned = true;
}
if (this == block && at == 0)
{
mPatchUsed = used;
}
else
{
mPatchUsed = used || !cleared;
if (mTrueJump && !mTrueJump->CheckSingleUseGlobalLoadStruct(block, rins, 0, ains, cleared, poisoned))
return false;
if (mFalseJump && !mFalseJump->CheckSingleUseGlobalLoadStruct(block, rins, 0, ains, cleared, poisoned))
return false;
mPatchUsed = used || (mTrueJump && mTrueJump->mPatchUsed) || (mFalseJump && mFalseJump->mPatchUsed);
}
}
else if (mPatchUsed && (poisoned || cleared))
return false;
return true;
}
bool NativeCodeBasicBlock::PatchSingleUseGlobalLoadStruct(const NativeCodeBasicBlock* block, const NativeCodeInstruction& rins, int at, const NativeCodeInstruction& ains)
{
bool changed = false;
if (!mPatched)
{
if (at == 0)
mPatched = true;
bool cleared = false;
for (int i = at; i < mIns.Size() && !cleared; i++)
{
NativeCodeInstruction& ins(mIns[i]);
if (ins.SameEffectiveAddress(rins))
{
if (ins.mType == ASMIT_LDA)
{
ins.CopyMode(ains);
changed = true;
}
else if (ins.mType == ASMIT_STA || ins.mType == ASMIT_STX || ins.mType == ASMIT_STY)
cleared = true;
}
}
if (!cleared)
{
if (mTrueJump && !mTrueJump->PatchSingleUseGlobalLoadStruct(block, rins, 0, ains))
changed = true;
if (mFalseJump && !mFalseJump->PatchSingleUseGlobalLoadStruct(block, rins, 0, ains))
changed = true;
}
}
return changed;
}
bool NativeCodeBasicBlock::CheckForwardLowYPointer(const NativeCodeBasicBlock* block, int reg, int yreg, int at, int yval) bool NativeCodeBasicBlock::CheckForwardLowYPointer(const NativeCodeBasicBlock* block, int reg, int yreg, int at, int yval)
{ {
// Checking only current block as first optimization step // Checking only current block as first optimization step
@ -44004,6 +44124,35 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc, int xen
} }
break; break;
case ASMIT_ADC: case ASMIT_ADC:
{
if (mIns[i].mMode == ASMIM_IMMEDIATE)
{
int amax = ((accuVal & accuMask) | (~accuMask & 255)) + mIns[i].mAddress;
if (!carryClear)
amax++;
if (amax < 256)
{
carryClear = true;
carrySet = false;
accuMask = ~BinMask(accuMask) & 255;
accuVal = 0;
}
else
{
accuMask = 0;
accuFlags = true;
carryClear = false;
carrySet = false;
}
}
else
{
accuMask = 0;
accuFlags = true;
carryClear = false;
carrySet = false;
}
} break;
case ASMIT_SBC: case ASMIT_SBC:
accuMask = 0; accuMask = 0;
accuFlags = true; accuFlags = true;
@ -51659,6 +51808,29 @@ bool NativeCodeBasicBlock::PeepHoleOptimizerIterate(int pass)
if (mFalseJump) if (mFalseJump)
mFalseJump->CheckLive(); mFalseJump->CheckLive();
#if 1
if (pass == 8 && i + 1 < mIns.Size() && (mProc->mCompilerOptions & COPT_OPTIMIZE_BASIC))
{
if (
mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_ABSOLUTE_X || mIns[i + 0].mMode == ASMIM_ABSOLUTE_Y) &&
!(mIns[i + 0].mFlags & NCIF_VOLATILE) &&
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ABSOLUTE && mIns[i + 1].mLinkerObject &&
mIns[i + 1].mLinkerObject->mVariable && (mIns[i + 1].mLinkerObject->mFlags & LOBJF_LOCAL_VAR))
{
mProc->ResetPatched();
if (CheckSingleUseGlobalLoadStruct(this, mIns[i + 1], i + 2, mIns[i + 0], false, false))
{
mProc->ResetPatched();
if (PatchSingleUseGlobalLoadStruct(this, mIns[i + 1], i + 2, mIns[i + 0]))
{
mIns[i + 1].mType = ASMIT_NOP;
mIns[i + 1].mMode = ASMIM_IMPLIED;
changed = true;
}
}
}
}
#endif
#if 1 #if 1
if (pass < 10 && i + 1 < mIns.Size()) if (pass < 10 && i + 1 < mIns.Size())
{ {
@ -52719,6 +52891,26 @@ bool NativeCodeBasicBlock::PeepHoleOptimizerExits(int pass)
} }
} }
#endif #endif
sz = mIns.Size();
if (sz >= 4 && mFalseJump && (mBranch == ASMIT_BPL || mBranch == ASMIT_BMI))
{
if (mIns[sz - 4].mType == ASMIT_TAY &&
mIns[sz - 3].mType == ASMIT_ASL && mIns[sz - 3].mMode == ASMIM_IMPLIED &&
mIns[sz - 2].mType == ASMIT_TAX &&
mIns[sz - 1].mType == ASMIT_TYA && !(mIns[sz - 1].mLive & LIVE_CPU_REG_A))
{
mIns[sz - 3].mLive |= LIVE_CPU_REG_C;
mIns[sz - 2].mLive |= LIVE_CPU_REG_C;
mIns[sz - 1].mType = ASMIT_NOP;
if (mBranch == ASMIT_BPL)
mBranch = ASMIT_BCC;
else
mBranch = ASMIT_BCS;
changed = true;
}
}
#if 1 #if 1
if (pass > 15 && sz > 0 && (mIns[sz - 1].mType == ASMIT_CMP || mIns[sz - 1].mType == ASMIT_CPX || mIns[sz - 1].mType == ASMIT_CPY)) if (pass > 15 && sz > 0 && (mIns[sz - 1].mType == ASMIT_CMP || mIns[sz - 1].mType == ASMIT_CPX || mIns[sz - 1].mType == ASMIT_CPY))
{ {
@ -56039,6 +56231,7 @@ void NativeCodeProcedure::ResetPatched(void)
NativeCodeBasicBlock* b = mBlocks[i]; NativeCodeBasicBlock* b = mBlocks[i];
b->mPatched = false; b->mPatched = false;
b->mPatchFail = false; b->mPatchFail = false;
b->mPatchUsed = false;
b->mPatchChecked = false; b->mPatchChecked = false;
b->mPatchStart = false; b->mPatchStart = false;
b->mPatchLoop = false; b->mPatchLoop = false;

View File

@ -198,6 +198,7 @@ public:
bool UsesZeroPage(int address) const; bool UsesZeroPage(int address) const;
bool ReferencesZeroPage(int address) const; bool ReferencesZeroPage(int address) const;
bool SameLinkerObjectVariableRange(const NativeCodeInstruction& ins, bool sameXY = false) const;
bool ChangesGlobalMemory(void) const; bool ChangesGlobalMemory(void) const;
bool UsesMemoryOf(const NativeCodeInstruction& ins) const; bool UsesMemoryOf(const NativeCodeInstruction& ins) const;
@ -259,7 +260,7 @@ public:
ExpandingArray<NativeCodeBasicBlock*> mEntryBlocks; ExpandingArray<NativeCodeBasicBlock*> mEntryBlocks;
int mOffset, mSize, mPlace, mNumEntries, mNumEntered, mFrameOffset, mTemp; int mOffset, mSize, mPlace, mNumEntries, mNumEntered, mFrameOffset, mTemp;
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited, mLoopHead, mVisiting, mLocked, mPatched, mPatchFail, mPatchChecked, mPatchStart, mPatchLoop, mPatchLoopChanged, mPatchExit; bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited, mLoopHead, mVisiting, mLocked, mPatched, mPatchFail, mPatchChecked, mPatchUsed, mPatchStart, mPatchLoop, mPatchLoopChanged, mPatchExit;
bool mEntryRegA, mEntryRegX, mEntryRegY, mExitRegA, mExitRegX, mChecked; bool mEntryRegA, mEntryRegX, mEntryRegY, mExitRegA, mExitRegX, mChecked;
NativeCodeBasicBlock * mDominator, * mSameBlock; NativeCodeBasicBlock * mDominator, * mSameBlock;
@ -798,9 +799,20 @@ public:
bool CheckGlobalAddressSumYPointer(const NativeCodeBasicBlock * block, int reg, int index, int at, int yval); bool CheckGlobalAddressSumYPointer(const NativeCodeBasicBlock * block, int reg, int index, int at, int yval);
bool PatchGlobalAddressSumYPointer(const NativeCodeBasicBlock* block, int reg, int index, int at, int yval, LinkerObject * lobj, int address, uint32 flags = NCIF_LOWER | NCIF_UPPER); bool PatchGlobalAddressSumYPointer(const NativeCodeBasicBlock* block, int reg, int index, int at, int yval, LinkerObject * lobj, int address, uint32 flags = NCIF_LOWER | NCIF_UPPER);
// reg : register to replace
// at : start position in block
// ains : instruction loading original data
// cycles : max number of cycles saving
bool CheckSingleUseGlobalLoad(const NativeCodeBasicBlock* block, int reg, int at, const NativeCodeInstruction& ains, int cycles); bool CheckSingleUseGlobalLoad(const NativeCodeBasicBlock* block, int reg, int at, const NativeCodeInstruction& ains, int cycles);
bool PatchSingleUseGlobalLoad(const NativeCodeBasicBlock* block, int reg, int at, const NativeCodeInstruction& ains); bool PatchSingleUseGlobalLoad(const NativeCodeBasicBlock* block, int reg, int at, const NativeCodeInstruction& ains);
// rins : instruction storing the data
// at : start position in block
// ains : instruction loading original data
// cycles : max number of cycles saving
bool CheckSingleUseGlobalLoadStruct(const NativeCodeBasicBlock* block, const NativeCodeInstruction& rins, int at, const NativeCodeInstruction& ains, bool cleared, bool poisoned);
bool PatchSingleUseGlobalLoadStruct(const NativeCodeBasicBlock* block, const NativeCodeInstruction& rins, int at, const NativeCodeInstruction& ains);
// reg : base register pair to replace // reg : base register pair to replace
// base: new base register // base: new base register
// iins : indexing instruction // iins : indexing instruction

View File

@ -5935,6 +5935,25 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec)
Declaration* Parser::ParseQualIdent(bool lhs) Declaration* Parser::ParseQualIdent(bool lhs)
{ {
Declaration* dec = nullptr; Declaration* dec = nullptr;
if (mScanner->mToken == TK_COLCOLON)
{
mScanner->NextToken();
if (mScanner->mToken == TK_IDENT)
{
DeclarationScope* scope = mScope;
while (scope->mLevel > SLEVEL_STATIC)
scope = scope->mParent;
dec = scope->Lookup(mScanner->mTokenIdent);
}
else
{
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected");
return nullptr;
}
}
else
{
if (mTemplateScope) if (mTemplateScope)
{ {
dec = mTemplateScope->Lookup(mScanner->mTokenIdent); dec = mTemplateScope->Lookup(mScanner->mTokenIdent);
@ -5942,6 +5961,7 @@ Declaration* Parser::ParseQualIdent(bool lhs)
if (!dec) if (!dec)
dec = mScope->Lookup(mScanner->mTokenIdent); dec = mScope->Lookup(mScanner->mTokenIdent);
}
if (dec) if (dec)
{ {
@ -6370,6 +6390,123 @@ Expression* Parser::ParseCastExpression(Expression* exp)
return exp; return exp;
} }
Expression* Parser::ParseIdentExpression(const Location & eloc, Declaration* dec, bool lhs, bool tid)
{
Expression* exp = nullptr;
if (dec->mTemplate && mScanner->mToken == TK_LESS_THAN)
{
dec = ParseTemplateExpansion(dec->mTemplate, nullptr);
while (ConsumeTokenIf(TK_COLCOLON))
{
if (mScanner->mToken == TK_IDENT)
{
if (dec->mType == DT_NAMESPACE || dec->mType == DT_TYPE_STRUCT || dec->mType == DT_TYPE_ENUM)
{
Declaration* ndec = dec->mScope->Lookup(mScanner->mTokenIdent, SLEVEL_USING);
if (ndec)
dec = ndec;
else
mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown identifier", mScanner->mTokenIdent);
}
else
mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a class or namespace");
}
else
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected");
mScanner->NextToken();
}
}
if (dec->mType == DT_CONST_INTEGER || dec->mType == DT_CONST_FLOAT || dec->mType == DT_CONST_FUNCTION || dec->mType == DT_CONST_ASSEMBLER || dec->mType == DT_LABEL || dec->mType == DT_LABEL_REF)
{
exp = new Expression(eloc, EX_CONSTANT);
exp->mDecValue = dec;
exp->mDecType = dec->mBase;
exp->mConst = true;
}
else if (dec->mType == DT_VARIABLE || dec->mType == DT_ARGUMENT)
{
if (/*(dec->mFlags & DTF_STATIC) &&*/ (dec->mFlags & DTF_CONST) && dec->mValue)
{
if (dec->mBase->IsNumericType())
{
if (dec->mValue->mType == EX_CONSTANT)
{
exp = dec->mValue;
}
}
else if (dec->mBase->mType == DT_TYPE_POINTER)
{
if (dec->mValue->mType == EX_CONSTANT)
{
if (dec->mValue->mDecValue->mType == DT_CONST_ADDRESS || dec->mValue->mDecValue->mType == DT_CONST_POINTER)
exp = dec->mValue;
}
}
}
if (!exp)
{
exp = new Expression(eloc, EX_VARIABLE);
exp->mDecValue = dec;
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_PACK_TYPE)
{
exp = new Expression(mScanner->mLocation, EX_PACK_TYPE);
exp->mDecValue = nullptr;
exp->mDecType = dec;
}
else if (dec->mType <= DT_TYPE_FUNCTION)
{
if (lhs)
exp = ParseDeclarationExpression(dec);
else
{
exp = new Expression(mScanner->mLocation, EX_TYPE);
exp->mDecValue = nullptr;
exp->mDecType = ParseTypeID(tid, dec);
}
}
else if (dec->mType == DT_CONST_TEMPLATE)
{
exp = new Expression(mScanner->mLocation, EX_CONSTANT);
exp->mDecValue = dec;
exp->mDecType = TheSignedIntTypeDeclaration;
}
else if (dec->mType == DT_PACK_TEMPLATE)
{
exp = new Expression(mScanner->mLocation, EX_PACK_TYPE);
exp->mDecType = dec;
}
else if (dec->mType == DT_ELEMENT)
{
mErrors->Error(mScanner->mLocation, EERR_NON_STATIC_MEMBER, "Non static member access", mScanner->mTokenIdent);
}
else if (dec->mType == DT_CLABEL)
{
exp = new Expression(dec->mLocation, EX_LABEL);
exp->mDecValue = dec;
}
else
{
mErrors->Error(mScanner->mLocation, EERR_INVALID_IDENTIFIER, "Invalid identifier", mScanner->mTokenIdent);
}
return exp;
}
Expression* Parser::ParseSimpleExpression(bool lhs, bool tid) Expression* Parser::ParseSimpleExpression(bool lhs, bool tid)
{ {
Declaration* dec = nullptr; Declaration* dec = nullptr;
@ -6596,6 +6733,12 @@ Expression* Parser::ParseSimpleExpression(bool lhs, bool tid)
mScanner->NextToken(); mScanner->NextToken();
break; break;
case TK_COLCOLON:
dec = ParseQualIdent(lhs);
if (dec)
exp = ParseIdentExpression(eloc, dec, lhs);
break;
case TK_IDENT: case TK_IDENT:
if (mLambda && mCaptureToken != TK_NONE && !mScope->Lookup(mScanner->mTokenIdent, SLEVEL_CLASS) && !mLambda->mScope->Lookup(mScanner->mTokenIdent, SLEVEL_CLASS)) if (mLambda && mCaptureToken != TK_NONE && !mScope->Lookup(mScanner->mTokenIdent, SLEVEL_CLASS) && !mLambda->mScope->Lookup(mScanner->mTokenIdent, SLEVEL_CLASS))
{ {
@ -6670,117 +6813,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs, bool tid)
if (!dec) if (!dec)
dec = ParseQualIdent(lhs); dec = ParseQualIdent(lhs);
if (dec) if (dec)
{ exp = ParseIdentExpression(eloc, dec, lhs, tid);
if (dec->mTemplate && mScanner->mToken == TK_LESS_THAN)
{
dec = ParseTemplateExpansion(dec->mTemplate, nullptr);
while (ConsumeTokenIf(TK_COLCOLON))
{
if (mScanner->mToken == TK_IDENT)
{
if (dec->mType == DT_NAMESPACE || dec->mType == DT_TYPE_STRUCT || dec->mType == DT_TYPE_ENUM)
{
Declaration* ndec = dec->mScope->Lookup(mScanner->mTokenIdent, SLEVEL_USING);
if (ndec)
dec = ndec;
else
mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown identifier", mScanner->mTokenIdent);
}
else
mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a class or namespace");
}
else
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected");
mScanner->NextToken();
}
}
if (dec->mType == DT_CONST_INTEGER || dec->mType == DT_CONST_FLOAT || dec->mType == DT_CONST_FUNCTION || dec->mType == DT_CONST_ASSEMBLER || dec->mType == DT_LABEL || dec->mType == DT_LABEL_REF)
{
exp = new Expression(eloc, EX_CONSTANT);
exp->mDecValue = dec;
exp->mDecType = dec->mBase;
exp->mConst = true;
}
else if (dec->mType == DT_VARIABLE || dec->mType == DT_ARGUMENT)
{
if (/*(dec->mFlags & DTF_STATIC) &&*/ (dec->mFlags & DTF_CONST) && dec->mValue)
{
if (dec->mBase->IsNumericType())
{
if (dec->mValue->mType == EX_CONSTANT)
{
exp = dec->mValue;
}
}
else if (dec->mBase->mType == DT_TYPE_POINTER)
{
if (dec->mValue->mType == EX_CONSTANT)
{
if (dec->mValue->mDecValue->mType == DT_CONST_ADDRESS || dec->mValue->mDecValue->mType == DT_CONST_POINTER)
exp = dec->mValue;
}
}
}
if (!exp)
{
exp = new Expression(eloc, EX_VARIABLE);
exp->mDecValue = dec;
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_PACK_TYPE)
{
exp = new Expression(mScanner->mLocation, EX_PACK_TYPE);
exp->mDecValue = nullptr;
exp->mDecType = dec;
}
else if (dec->mType <= DT_TYPE_FUNCTION)
{
if (lhs)
exp = ParseDeclarationExpression(dec);
else
{
exp = new Expression(mScanner->mLocation, EX_TYPE);
exp->mDecValue = nullptr;
exp->mDecType = ParseTypeID(tid, dec);
}
}
else if (dec->mType == DT_CONST_TEMPLATE)
{
exp = new Expression(mScanner->mLocation, EX_CONSTANT);
exp->mDecValue = dec;
exp->mDecType = TheSignedIntTypeDeclaration;
}
else if (dec->mType == DT_PACK_TEMPLATE)
{
exp = new Expression(mScanner->mLocation, EX_PACK_TYPE);
exp->mDecType = dec;
}
else if (dec->mType == DT_ELEMENT)
{
mErrors->Error(mScanner->mLocation, EERR_NON_STATIC_MEMBER, "Non static member access", mScanner->mTokenIdent);
}
else if (dec->mType == DT_CLABEL)
{
exp = new Expression(dec->mLocation, EX_LABEL);
exp->mDecValue = dec;
}
else
{
mErrors->Error(mScanner->mLocation, EERR_INVALID_IDENTIFIER, "Invalid identifier", mScanner->mTokenIdent);
}
}
} }
break; break;

View File

@ -134,6 +134,7 @@ protected:
Declaration* ParseTypeID(bool tid, Declaration * bdec = nullptr); Declaration* ParseTypeID(bool tid, Declaration * bdec = nullptr);
Expression* ParseCastExpression(Expression* exp); Expression* ParseCastExpression(Expression* exp);
Expression* ParseIdentExpression(const Location & eloc, Declaration* dec, bool lhs, bool tid = false);
Expression* ParseSimpleExpression(bool lhs, bool tid = false); Expression* ParseSimpleExpression(bool lhs, bool tid = false);
Expression* ParsePrefixExpression(bool lhs); Expression* ParsePrefixExpression(bool lhs);
Expression* ParsePostfixExpression(bool lhs); Expression* ParsePostfixExpression(bool lhs);