Add ranges in case statements (gcc extension)
This commit is contained in:
parent
dcebdeaa5f
commit
4fc3e019d5
|
@ -19398,7 +19398,7 @@ void InterCodeProcedure::Close(void)
|
||||||
{
|
{
|
||||||
GrowingTypeArray tstack(IT_NONE);
|
GrowingTypeArray tstack(IT_NONE);
|
||||||
|
|
||||||
CheckFunc = !strcmp(mIdent->mString, "main");
|
CheckFunc = !strcmp(mIdent->mString, "JSONParser::Next");
|
||||||
CheckCase = false;
|
CheckCase = false;
|
||||||
|
|
||||||
mEntryBlock = mBlocks[0];
|
mEntryBlock = mBlocks[0];
|
||||||
|
@ -20269,6 +20269,9 @@ void InterCodeProcedure::Close(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
BuildDataFlowSets();
|
||||||
|
TempForwarding(false, true);
|
||||||
|
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->SingleLoopCountZeroCheck();
|
mEntryBlock->SingleLoopCountZeroCheck();
|
||||||
|
|
||||||
|
|
|
@ -1120,11 +1120,13 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e
|
||||||
|
|
||||||
InterInstruction* vins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT);
|
InterInstruction* vins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT);
|
||||||
vins->mConst.mType = IT_INT16;
|
vins->mConst.mType = IT_INT16;
|
||||||
vins->mConst.mIntConst = nodes[i].mValue;
|
vins->mConst.mIntConst = nodes[i].mLower;
|
||||||
vins->mDst.mType = IT_INT16;
|
vins->mDst.mType = IT_INT16;
|
||||||
vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType);
|
vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType);
|
||||||
block->Append(vins);
|
block->Append(vins);
|
||||||
|
|
||||||
|
if (nodes[i].mLower == nodes[i].mUpper)
|
||||||
|
{
|
||||||
InterInstruction* cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_RELATIONAL_OPERATOR);
|
InterInstruction* cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_RELATIONAL_OPERATOR);
|
||||||
cins->mOperator = IA_CMPEQ;
|
cins->mOperator = IA_CMPEQ;
|
||||||
cins->mSrc[0].mType = vins->mDst.mType;
|
cins->mSrc[0].mType = vins->mDst.mType;
|
||||||
|
@ -1140,13 +1142,59 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e
|
||||||
bins->mSrc[0].mType = IT_BOOL;
|
bins->mSrc[0].mType = IT_BOOL;
|
||||||
bins->mSrc[0].mTemp = cins->mDst.mTemp;
|
bins->mSrc[0].mTemp = cins->mDst.mTemp;
|
||||||
block->Append(bins);
|
block->Append(bins);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InterCodeBasicBlock* tblock = new InterCodeBasicBlock(proc);
|
||||||
|
|
||||||
|
InterInstruction* cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_RELATIONAL_OPERATOR);
|
||||||
|
cins->mOperator = IA_CMPLS;
|
||||||
|
cins->mSrc[0].mType = vins->mDst.mType;
|
||||||
|
cins->mSrc[0].mTemp = vins->mDst.mTemp;
|
||||||
|
cins->mSrc[1].mType = vins->mDst.mType;
|
||||||
|
cins->mSrc[1].mTemp = v.mTemp;
|
||||||
|
cins->mDst.mType = IT_BOOL;
|
||||||
|
cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType);
|
||||||
|
|
||||||
|
block->Append(cins);
|
||||||
|
|
||||||
|
InterInstruction* bins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BRANCH);
|
||||||
|
bins->mSrc[0].mType = IT_BOOL;
|
||||||
|
bins->mSrc[0].mTemp = cins->mDst.mTemp;
|
||||||
|
block->Append(bins);
|
||||||
|
block->Close(cblock, tblock);
|
||||||
|
|
||||||
|
block = tblock;
|
||||||
|
|
||||||
|
InterInstruction* vins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT);
|
||||||
|
vins->mConst.mType = IT_INT16;
|
||||||
|
vins->mConst.mIntConst = nodes[i].mUpper;
|
||||||
|
vins->mDst.mType = IT_INT16;
|
||||||
|
vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType);
|
||||||
|
block->Append(vins);
|
||||||
|
|
||||||
|
cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_RELATIONAL_OPERATOR);
|
||||||
|
cins->mOperator = IA_CMPLES;
|
||||||
|
cins->mSrc[0].mType = vins->mDst.mType;
|
||||||
|
cins->mSrc[0].mTemp = vins->mDst.mTemp;
|
||||||
|
cins->mSrc[1].mType = vins->mDst.mType;
|
||||||
|
cins->mSrc[1].mTemp = v.mTemp;
|
||||||
|
cins->mDst.mType = IT_BOOL;
|
||||||
|
cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType);
|
||||||
|
block->Append(cins);
|
||||||
|
|
||||||
|
bins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BRANCH);
|
||||||
|
bins->mSrc[0].mType = IT_BOOL;
|
||||||
|
bins->mSrc[0].mTemp = cins->mDst.mTemp;
|
||||||
|
block->Append(bins);
|
||||||
|
}
|
||||||
|
|
||||||
block->Close(nodes[i].mBlock, cblock);
|
block->Close(nodes[i].mBlock, cblock);
|
||||||
|
|
||||||
block = cblock;
|
block = cblock;
|
||||||
|
|
||||||
if (vleft == nodes[i].mValue)
|
if (vleft == nodes[i].mLower)
|
||||||
vleft = nodes[i].mValue + 1;
|
vleft = nodes[i].mLower + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1158,12 +1206,15 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int center = (left + right) >> 1;
|
int center = (left + right) >> 1;
|
||||||
int vcenter = nodes[center].mValue;
|
|
||||||
|
|
||||||
InterCodeBasicBlock* cblock = new InterCodeBasicBlock(proc);
|
InterCodeBasicBlock* cblock = new InterCodeBasicBlock(proc);
|
||||||
InterCodeBasicBlock* rblock = new InterCodeBasicBlock(proc);
|
InterCodeBasicBlock* rblock = new InterCodeBasicBlock(proc);
|
||||||
InterCodeBasicBlock* lblock = new InterCodeBasicBlock(proc);
|
InterCodeBasicBlock* lblock = new InterCodeBasicBlock(proc);
|
||||||
|
|
||||||
|
if (nodes[center].mLower == nodes[center].mUpper)
|
||||||
|
{
|
||||||
|
int vcenter = nodes[center].mLower;
|
||||||
|
|
||||||
InterInstruction* vins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT);
|
InterInstruction* vins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT);
|
||||||
vins->mConst.mType = IT_INT16;
|
vins->mConst.mType = IT_INT16;
|
||||||
vins->mConst.mIntConst = vcenter;
|
vins->mConst.mIntConst = vcenter;
|
||||||
|
@ -1210,6 +1261,63 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e
|
||||||
BuildSwitchTree(proc, exp, lblock, inlineMapper, v, nodes, left, center, vleft, vcenter - 1, dblock);
|
BuildSwitchTree(proc, exp, lblock, inlineMapper, v, nodes, left, center, vleft, vcenter - 1, dblock);
|
||||||
BuildSwitchTree(proc, exp, rblock, inlineMapper, v, nodes, center + 1, right, vcenter + 1, vright, dblock);
|
BuildSwitchTree(proc, exp, rblock, inlineMapper, v, nodes, center + 1, right, vcenter + 1, vright, dblock);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int vlower = nodes[center].mLower, vupper = nodes[center].mUpper;
|
||||||
|
|
||||||
|
InterInstruction* vins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT);
|
||||||
|
vins->mConst.mType = IT_INT16;
|
||||||
|
vins->mConst.mIntConst = vlower;
|
||||||
|
vins->mDst.mType = IT_INT16;
|
||||||
|
vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType);
|
||||||
|
block->Append(vins);
|
||||||
|
|
||||||
|
InterInstruction* cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_RELATIONAL_OPERATOR);
|
||||||
|
cins->mOperator = IA_CMPLS;
|
||||||
|
cins->mSrc[0].mType = vins->mDst.mType;
|
||||||
|
cins->mSrc[0].mTemp = vins->mDst.mTemp;
|
||||||
|
cins->mSrc[1].mType = vins->mDst.mType;
|
||||||
|
cins->mSrc[1].mTemp = v.mTemp;
|
||||||
|
cins->mDst.mType = IT_BOOL;
|
||||||
|
cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType);
|
||||||
|
|
||||||
|
block->Append(cins);
|
||||||
|
|
||||||
|
InterInstruction* bins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BRANCH);
|
||||||
|
bins->mSrc[0].mType = IT_BOOL;
|
||||||
|
bins->mSrc[0].mTemp = cins->mDst.mTemp;
|
||||||
|
block->Append(bins);
|
||||||
|
block->Close(lblock, cblock);
|
||||||
|
|
||||||
|
vins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT);
|
||||||
|
vins->mConst.mType = IT_INT16;
|
||||||
|
vins->mConst.mIntConst = vupper;
|
||||||
|
vins->mDst.mType = IT_INT16;
|
||||||
|
vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType);
|
||||||
|
cblock->Append(vins);
|
||||||
|
|
||||||
|
cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_RELATIONAL_OPERATOR);
|
||||||
|
cins->mOperator = IA_CMPLES;
|
||||||
|
cins->mSrc[0].mType = vins->mDst.mType;
|
||||||
|
cins->mSrc[0].mTemp = vins->mDst.mTemp;
|
||||||
|
cins->mSrc[1].mType = vins->mDst.mType;
|
||||||
|
cins->mSrc[1].mTemp = v.mTemp;
|
||||||
|
cins->mDst.mType = IT_BOOL;
|
||||||
|
cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType);
|
||||||
|
cblock->Append(cins);
|
||||||
|
|
||||||
|
bins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BRANCH);
|
||||||
|
bins->mSrc[0].mType = IT_BOOL;
|
||||||
|
bins->mSrc[0].mTemp = cins->mDst.mTemp;
|
||||||
|
cblock->Append(bins);
|
||||||
|
|
||||||
|
cblock->Close(nodes[center].mBlock, rblock);
|
||||||
|
|
||||||
|
BuildSwitchTree(proc, exp, lblock, inlineMapper, v, nodes, left, center, vleft, vlower - 1, dblock);
|
||||||
|
BuildSwitchTree(proc, exp, rblock, inlineMapper, v, nodes, center + 1, right, vupper + 1, vright, dblock);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterCodeGenerator::UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack* bottom, InlineMapper* inlineMapper)
|
void InterCodeGenerator::UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack* bottom, InlineMapper* inlineMapper)
|
||||||
|
@ -4881,24 +4989,41 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
Expression* cexp = sexp->mLeft;
|
Expression* cexp = sexp->mLeft;
|
||||||
if (cexp->mType == EX_CASE)
|
if (cexp->mType == EX_CASE)
|
||||||
{
|
{
|
||||||
InterCodeBasicBlock* nblock = new InterCodeBasicBlock(proc);
|
|
||||||
|
|
||||||
SwitchNode snode;
|
SwitchNode snode;
|
||||||
snode.mBlock = nblock;
|
snode.mLower = snode.mUpper = 0;
|
||||||
snode.mValue = 0;
|
snode.mBlock = nullptr;
|
||||||
|
|
||||||
if (cexp->mLeft->mType == EX_CONSTANT && cexp->mLeft->mDecValue->mType == DT_CONST_INTEGER)
|
if (cexp->mLeft->mType == EX_CONSTANT && cexp->mLeft->mDecValue->mType == DT_CONST_INTEGER)
|
||||||
snode.mValue = int(cexp->mLeft->mDecValue->mInteger);
|
snode.mLower = snode.mUpper = int(cexp->mLeft->mDecValue->mInteger);
|
||||||
|
else if (cexp->mLeft->mType == EX_LIST)
|
||||||
|
{
|
||||||
|
Expression* rexp = cexp->mLeft;
|
||||||
|
|
||||||
|
if (rexp->mLeft->mType == EX_CONSTANT && rexp->mLeft->mDecValue->mType == DT_CONST_INTEGER &&
|
||||||
|
rexp->mRight->mType == EX_CONSTANT && rexp->mRight->mDecValue->mType == DT_CONST_INTEGER)
|
||||||
|
{
|
||||||
|
snode.mLower = int(rexp->mLeft->mDecValue->mInteger);
|
||||||
|
snode.mUpper = int(rexp->mRight->mDecValue->mInteger);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mErrors->Error(cexp->mLeft->mLocation, ERRR_INVALID_CASE, "Integral constant range expected");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
mErrors->Error(cexp->mLeft->mLocation, ERRR_INVALID_CASE, "Integral constant expected");
|
mErrors->Error(cexp->mLeft->mLocation, ERRR_INVALID_CASE, "Integral constant expected");
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < switchNodes.Size() && switchNodes[i].mValue < snode.mValue)
|
while (i < switchNodes.Size() && snode.mLower > switchNodes[i].mLower)
|
||||||
i++;
|
i++;
|
||||||
if (i < switchNodes.Size() && switchNodes[i].mValue == snode.mValue)
|
if (i < switchNodes.Size() && snode.mUpper >= switchNodes[i].mLower)
|
||||||
mErrors->Error(exp->mLeft->mLocation, ERRR_INVALID_CASE, "Duplicate case constant");
|
mErrors->Error(cexp->mLeft->mLocation, ERRR_INVALID_CASE, "Duplicate case constant");
|
||||||
else
|
else
|
||||||
switchNodes.Insert(i, snode);
|
{
|
||||||
|
if (block && block->mInstructions.Size() == 0)
|
||||||
|
snode.mBlock = block;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InterCodeBasicBlock* nblock = new InterCodeBasicBlock(proc);
|
||||||
|
snode.mBlock = nblock;
|
||||||
|
|
||||||
if (block)
|
if (block)
|
||||||
{
|
{
|
||||||
|
@ -4910,6 +5035,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
|
|
||||||
block = nblock;
|
block = nblock;
|
||||||
}
|
}
|
||||||
|
switchNodes.Insert(i, snode);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (cexp->mType == EX_DEFAULT)
|
else if (cexp->mType == EX_DEFAULT)
|
||||||
{
|
{
|
||||||
if (!dblock)
|
if (!dblock)
|
||||||
|
@ -4936,6 +5064,16 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
sexp = sexp->mRight;
|
sexp = sexp->mRight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int i = 1, j = 1;
|
||||||
|
while (i < switchNodes.Size())
|
||||||
|
{
|
||||||
|
if (switchNodes[i].mBlock == switchNodes[j - 1].mBlock && switchNodes[i].mLower == switchNodes[j - 1].mUpper + 1)
|
||||||
|
switchNodes[j - 1].mUpper = switchNodes[i].mUpper;
|
||||||
|
else
|
||||||
|
switchNodes[j++] = switchNodes[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
switchNodes.SetSize(j);
|
||||||
|
|
||||||
BuildSwitchTree(proc, exp, sblock, inlineMapper, vl, switchNodes, 0, switchNodes.Size(), vleft, vright, dblock ? dblock : eblock);
|
BuildSwitchTree(proc, exp, sblock, inlineMapper, vl, switchNodes, 0, switchNodes.Size(), vleft, vright, dblock ? dblock : eblock);
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ protected:
|
||||||
|
|
||||||
struct SwitchNode
|
struct SwitchNode
|
||||||
{
|
{
|
||||||
int mValue;
|
int mLower, mUpper;
|
||||||
InterCodeBasicBlock * mBlock;
|
InterCodeBasicBlock * mBlock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9219,6 +9219,14 @@ Expression* Parser::ParseSwitchStatement(void)
|
||||||
pexp = cexp;
|
pexp = cexp;
|
||||||
cexp->mLeft = ParseRExpression();
|
cexp->mLeft = ParseRExpression();
|
||||||
|
|
||||||
|
if (ConsumeTokenIf(TK_ELLIPSIS))
|
||||||
|
{
|
||||||
|
Expression* rexp = new Expression(mScanner->mLocation, EX_LIST);
|
||||||
|
rexp->mLeft = cexp->mLeft;
|
||||||
|
rexp->mRight = ParseRExpression();
|
||||||
|
cexp->mLeft = rexp;
|
||||||
|
}
|
||||||
|
|
||||||
if (mScanner->mToken == TK_COLON)
|
if (mScanner->mToken == TK_COLON)
|
||||||
mScanner->NextToken();
|
mScanner->NextToken();
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue