This commit is contained in:
rogerl%netscape.com 2000-04-01 02:53:16 +00:00
Родитель a319d852b3
Коммит 3714722cf4
6 изменённых файлов: 190 добавлений и 18 удалений

Просмотреть файл

@ -161,19 +161,19 @@ void ICodeGenerator::setLabel(InstructionStream *stream, int32 label)
/***********************************************************************************************/
void MultiPathICodeState::mergeStream(InstructionStream *mainStream, LabelList &labels)
void MultiPathICodeState::mergeStream(InstructionStream *sideStream, InstructionStream *mainStream, LabelList &labels)
{
// change InstructionStream to be a class that also remembers
// if it contains any labels (maybe even remembers the labels
// themselves?) in order to avoid running this loop unnecessarily.
for (LabelList::iterator i = labels.begin(); i != labels.end(); i++) {
if ((*i)->itsBase == its_iCode) {
if ((*i)->itsBase == sideStream) {
(*i)->itsBase = mainStream;
(*i)->itsOffset += mainStream->size();
}
}
for (InstructionIterator ii = its_iCode->begin(); ii != its_iCode->end(); ii++)
for (InstructionIterator ii = sideStream->begin(); ii != sideStream->end(); ii++)
mainStream->push_back(*ii);
}
@ -231,6 +231,66 @@ void ICodeGenerator::endWhileStatement()
/***********************************************************************************************/
void ICodeGenerator::beginForStatement(const SourcePosition &pos)
{
int32 forCondition = getLabel();
ForCodeState *ics = new ForCodeState(forCondition, getLabel(), this);
ics->continueLabel = getLabel();
branch(forCondition);
stitcher.push_back(ics);
iCode = new InstructionStream(); // begin the stream for collecting the test expression
setLabel(forCondition);
resetTopRegister();
}
void ICodeGenerator::forCondition(Register condition)
{
ForCodeState *ics = static_cast<ForCodeState *>(stitcher.back());
ASSERT(ics->stateKind == For_state);
// finsh off the test expression by adding the branch to the body
branchConditional(ics->forBody, condition);
iCode = ics->swapStream(iCode); // switch back to main stream
iCode = new InstructionStream(); // begin the stream for collecting the increment expression
setLabel(ics->continueLabel); // which is where continues will target
resetTopRegister();
}
void ICodeGenerator::forIncrement()
{
ForCodeState *ics = static_cast<ForCodeState *>(stitcher.back());
ASSERT(ics->stateKind == For_state);
// now switch back to the main stream
iCode = ics->swapStream2(iCode);
setLabel(ics->forBody);
resetTopRegister();
}
void ICodeGenerator::endForStatement()
{
ForCodeState *ics = static_cast<ForCodeState *>(stitcher.back());
ASSERT(ics->stateKind == For_state);
ics->mergeStream2(iCode, labels); // merges the increment sequence
ics->mergeStream(iCode, labels); // merges the test sequence
if (ics->breakLabel != -1)
setLabel(ics->breakLabel);
delete ics;
}
/***********************************************************************************************/
void ICodeGenerator::beginDoStatement(const SourcePosition &pos)
{
resetTopRegister();
@ -279,12 +339,12 @@ void ICodeGenerator::beginSwitchStatement(const SourcePosition &pos, Register ex
{
// stash the control expression value
resetTopRegister();
op(MOVE_TO, getRegister(), expression);
Register control = op(MOVE_TO, expression);
// build an instruction stream for the case statements, the case
// expressions are generated into the main stream directly, the
// case statements are then added back in afterwards.
InstructionStream *x = new InstructionStream();
SwitchCodeState *ics = new SwitchCodeState(expression, this);
SwitchCodeState *ics = new SwitchCodeState(control, this);
ics->swapStream(x);
stitcher.push_back(ics);
}

Просмотреть файл

@ -131,7 +131,9 @@ namespace JavaScript {
InstructionStream *its_iCode;
void mergeStream(InstructionStream *mainStream, LabelList &labels);
static void mergeStream(InstructionStream *sideStream, InstructionStream *mainStream, LabelList &labels);
void mergeStream(InstructionStream *mainStream, LabelList &labels) { mergeStream(its_iCode, mainStream, labels); }
};
class WhileCodeState : public MultiPathICodeState {
@ -142,6 +144,16 @@ namespace JavaScript {
int32 whileBody;
};
class ForCodeState : public MultiPathICodeState {
public:
ForCodeState(int32 conditionLabel, int32 bodyLabel, ICodeGenerator *icg); // inline below
InstructionStream *swapStream2(InstructionStream *iCode) { InstructionStream *t = its_iCode_2; its_iCode_2 = iCode; return t; }
void mergeStream2(InstructionStream *mainStream, LabelList &labels) { mergeStream(its_iCode_2, mainStream, labels); }
int32 forCondition;
int32 forBody;
InstructionStream *its_iCode_2;
};
class IfCodeState : public ICodeState {
public:
IfCodeState(int32 a, int32 b, ICodeGenerator *icg)
@ -241,9 +253,9 @@ namespace JavaScript {
// for ( ... in ...) statements get turned into generic for statements by the parser (ok?)
void beginForStatement(); // for initialization is emitted prior to this call
void forCondition(Register condition); // required with optional <operand>
void forIncrement(Register expression); // required with optional <operand>
void beginForStatement(const SourcePosition &pos); // for initialization is emitted prior to this call
void forCondition(Register condition); // required
void forIncrement(); // required
void endForStatement();
@ -290,5 +302,8 @@ namespace JavaScript {
inline MultiPathICodeState::MultiPathICodeState(StateKind kind, ICodeGenerator *icg)
: ICodeState(kind, icg), its_iCode(icg->get_iCode()) {}
inline ForCodeState::ForCodeState(int32 conditionLabel, int32 bodyLabel, ICodeGenerator *icg)
: MultiPathICodeState(For_state, icg), forCondition(conditionLabel), forBody(bodyLabel), its_iCode_2(icg->get_iCode()) { }
}
#endif

Просмотреть файл

@ -400,6 +400,17 @@ void testICG(World &world)
icg.endDefaultStatement();
icg.endSwitchStatement();
// for ( ; i; i + 1 ) j = 99;
icg.beginForStatement(pos);
r1 = icg.loadVariable(0);
icg.forCondition(r1);
icg.saveVariable(0, icg.op(ADD, icg.loadVariable(0), icg.loadImmediate(1)));
icg.forIncrement();
icg.saveVariable(0, icg.loadImmediate(99));
icg.endForStatement();
InstructionStream *iCode = icg.complete();
std::cout << icg;

Просмотреть файл

@ -161,19 +161,19 @@ void ICodeGenerator::setLabel(InstructionStream *stream, int32 label)
/***********************************************************************************************/
void MultiPathICodeState::mergeStream(InstructionStream *mainStream, LabelList &labels)
void MultiPathICodeState::mergeStream(InstructionStream *sideStream, InstructionStream *mainStream, LabelList &labels)
{
// change InstructionStream to be a class that also remembers
// if it contains any labels (maybe even remembers the labels
// themselves?) in order to avoid running this loop unnecessarily.
for (LabelList::iterator i = labels.begin(); i != labels.end(); i++) {
if ((*i)->itsBase == its_iCode) {
if ((*i)->itsBase == sideStream) {
(*i)->itsBase = mainStream;
(*i)->itsOffset += mainStream->size();
}
}
for (InstructionIterator ii = its_iCode->begin(); ii != its_iCode->end(); ii++)
for (InstructionIterator ii = sideStream->begin(); ii != sideStream->end(); ii++)
mainStream->push_back(*ii);
}
@ -231,6 +231,66 @@ void ICodeGenerator::endWhileStatement()
/***********************************************************************************************/
void ICodeGenerator::beginForStatement(const SourcePosition &pos)
{
int32 forCondition = getLabel();
ForCodeState *ics = new ForCodeState(forCondition, getLabel(), this);
ics->continueLabel = getLabel();
branch(forCondition);
stitcher.push_back(ics);
iCode = new InstructionStream(); // begin the stream for collecting the test expression
setLabel(forCondition);
resetTopRegister();
}
void ICodeGenerator::forCondition(Register condition)
{
ForCodeState *ics = static_cast<ForCodeState *>(stitcher.back());
ASSERT(ics->stateKind == For_state);
// finsh off the test expression by adding the branch to the body
branchConditional(ics->forBody, condition);
iCode = ics->swapStream(iCode); // switch back to main stream
iCode = new InstructionStream(); // begin the stream for collecting the increment expression
setLabel(ics->continueLabel); // which is where continues will target
resetTopRegister();
}
void ICodeGenerator::forIncrement()
{
ForCodeState *ics = static_cast<ForCodeState *>(stitcher.back());
ASSERT(ics->stateKind == For_state);
// now switch back to the main stream
iCode = ics->swapStream2(iCode);
setLabel(ics->forBody);
resetTopRegister();
}
void ICodeGenerator::endForStatement()
{
ForCodeState *ics = static_cast<ForCodeState *>(stitcher.back());
ASSERT(ics->stateKind == For_state);
ics->mergeStream2(iCode, labels); // merges the increment sequence
ics->mergeStream(iCode, labels); // merges the test sequence
if (ics->breakLabel != -1)
setLabel(ics->breakLabel);
delete ics;
}
/***********************************************************************************************/
void ICodeGenerator::beginDoStatement(const SourcePosition &pos)
{
resetTopRegister();
@ -279,12 +339,12 @@ void ICodeGenerator::beginSwitchStatement(const SourcePosition &pos, Register ex
{
// stash the control expression value
resetTopRegister();
op(MOVE_TO, getRegister(), expression);
Register control = op(MOVE_TO, expression);
// build an instruction stream for the case statements, the case
// expressions are generated into the main stream directly, the
// case statements are then added back in afterwards.
InstructionStream *x = new InstructionStream();
SwitchCodeState *ics = new SwitchCodeState(expression, this);
SwitchCodeState *ics = new SwitchCodeState(control, this);
ics->swapStream(x);
stitcher.push_back(ics);
}

Просмотреть файл

@ -131,7 +131,9 @@ namespace JavaScript {
InstructionStream *its_iCode;
void mergeStream(InstructionStream *mainStream, LabelList &labels);
static void mergeStream(InstructionStream *sideStream, InstructionStream *mainStream, LabelList &labels);
void mergeStream(InstructionStream *mainStream, LabelList &labels) { mergeStream(its_iCode, mainStream, labels); }
};
class WhileCodeState : public MultiPathICodeState {
@ -142,6 +144,16 @@ namespace JavaScript {
int32 whileBody;
};
class ForCodeState : public MultiPathICodeState {
public:
ForCodeState(int32 conditionLabel, int32 bodyLabel, ICodeGenerator *icg); // inline below
InstructionStream *swapStream2(InstructionStream *iCode) { InstructionStream *t = its_iCode_2; its_iCode_2 = iCode; return t; }
void mergeStream2(InstructionStream *mainStream, LabelList &labels) { mergeStream(its_iCode_2, mainStream, labels); }
int32 forCondition;
int32 forBody;
InstructionStream *its_iCode_2;
};
class IfCodeState : public ICodeState {
public:
IfCodeState(int32 a, int32 b, ICodeGenerator *icg)
@ -241,9 +253,9 @@ namespace JavaScript {
// for ( ... in ...) statements get turned into generic for statements by the parser (ok?)
void beginForStatement(); // for initialization is emitted prior to this call
void forCondition(Register condition); // required with optional <operand>
void forIncrement(Register expression); // required with optional <operand>
void beginForStatement(const SourcePosition &pos); // for initialization is emitted prior to this call
void forCondition(Register condition); // required
void forIncrement(); // required
void endForStatement();
@ -290,5 +302,8 @@ namespace JavaScript {
inline MultiPathICodeState::MultiPathICodeState(StateKind kind, ICodeGenerator *icg)
: ICodeState(kind, icg), its_iCode(icg->get_iCode()) {}
inline ForCodeState::ForCodeState(int32 conditionLabel, int32 bodyLabel, ICodeGenerator *icg)
: MultiPathICodeState(For_state, icg), forCondition(conditionLabel), forBody(bodyLabel), its_iCode_2(icg->get_iCode()) { }
}
#endif

Просмотреть файл

@ -400,6 +400,17 @@ void testICG(World &world)
icg.endDefaultStatement();
icg.endSwitchStatement();
// for ( ; i; i + 1 ) j = 99;
icg.beginForStatement(pos);
r1 = icg.loadVariable(0);
icg.forCondition(r1);
icg.saveVariable(0, icg.op(ADD, icg.loadVariable(0), icg.loadImmediate(1)));
icg.forIncrement();
icg.saveVariable(0, icg.loadImmediate(99));
icg.endForStatement();
InstructionStream *iCode = icg.complete();
std::cout << icg;