Began moving away from variables, fixed compare/branch ordering.

Testcases working.
This commit is contained in:
rogerl%netscape.com 2000-04-19 02:09:06 +00:00
Родитель d982d960b5
Коммит 7b7fc3829f
10 изменённых файлов: 116 добавлений и 134 удалений

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

@ -91,22 +91,6 @@ namespace ICG {
/********************************************************************/ /********************************************************************/
Register ICodeGenerator::loadVariable(uint32 frameIndex)
{
markMaxVariable(frameIndex);
Register dest = getRegister();
LoadVar *instr = new LoadVar(dest, frameIndex);
iCode->push_back(instr);
return dest;
}
void ICodeGenerator::saveVariable(uint32 frameIndex, Register value)
{
markMaxVariable(frameIndex);
SaveVar *instr = new SaveVar(frameIndex, value);
iCode->push_back(instr);
}
Register ICodeGenerator::loadImmediate(double value) Register ICodeGenerator::loadImmediate(double value)
{ {
Register dest = getRegister(); Register dest = getRegister();
@ -183,6 +167,12 @@ namespace ICG {
return dest; return dest;
} }
void ICodeGenerator::move(Register destination, Register source)
{
Move *instr = new Move(destination, source);
iCode->push_back(instr);
}
Register ICodeGenerator::op(ICodeOp op, Register source1, Register ICodeGenerator::op(ICodeOp op, Register source1,
Register source2) Register source2)
{ {
@ -638,4 +628,4 @@ namespace ICG {
} // namespace ICG } // namespace ICG
} // namespace JavaScript }; // namespace JavaScript

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

@ -107,10 +107,11 @@ namespace ICG {
{ if (variableIndex > maxVariable) maxVariable = variableIndex; } { if (variableIndex > maxVariable) maxVariable = variableIndex; }
Register topRegister; Register topRegister;
Register registerBase;
Register getRegister() \ Register getRegister() \
{ return topRegister++; } { return topRegister++; }
void resetTopRegister() \ void resetTopRegister() \
{ markMaxRegister(); topRegister = stitcher.empty() ? 0 : \ { markMaxRegister(); topRegister = stitcher.empty() ? registerBase : \
stitcher.back()->registerBase; } stitcher.back()->registerBase; }
ICodeOp getBranchOp() \ ICodeOp getBranchOp() \
@ -126,7 +127,7 @@ namespace ICG {
void branchConditional(Label *label, Register condition); void branchConditional(Label *label, Register condition);
public: public:
ICodeGenerator() : topRegister(0), maxRegister(0), ICodeGenerator() : topRegister(0), registerBase(0), maxRegister(0),
maxVariable(0) \ maxVariable(0) \
{ iCode = new InstructionStream(); } { iCode = new InstructionStream(); }
@ -135,12 +136,17 @@ namespace ICG {
void mergeStream(InstructionStream *sideStream); void mergeStream(InstructionStream *sideStream);
ICodeModule *complete(); ICodeModule *complete();
Register allocateVariable(StringAtom &name)
{ Register result = getRegister(); registerBase = topRegister; return result; }
Formatter& print(Formatter& f); Formatter& print(Formatter& f);
Register op(ICodeOp op, Register source); Register op(ICodeOp op, Register source);
Register op(ICodeOp op, Register source1, Register source2); Register op(ICodeOp op, Register source1, Register source2);
Register call(Register target, RegisterList args); Register call(Register target, RegisterList args);
void move(Register destination, Register source);
Register compare(ICodeOp op, Register source1, Register source2); Register compare(ICodeOp op, Register source1, Register source2);

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

@ -51,6 +51,7 @@ static void initConsole(StringPtr consoleName,
argc = 1; argc = 1;
argv = mac_argv; argv = mac_argv;
} }
#endif #endif
namespace JavaScript { namespace JavaScript {
@ -287,43 +288,41 @@ namespace JavaScript {
uint32 pos = 0; uint32 pos = 0;
ICodeGenerator icg; ICodeGenerator icg;
// var i,j; i = j + 2; // var i,j;
// i is bound to var #0, j to var #1 // i is bound to var #0, j to var #1
Register r_i = icg.allocateVariable(world.identifiers[widenCString("i")]);
Register r_j = icg.allocateVariable(world.identifiers[widenCString("j")]);
// i = j + 2;
icg.beginStatement(pos); icg.beginStatement(pos);
Register r1 = icg.loadVariable(1); Register r1 = icg.loadImmediate(2.0);
Register r2 = icg.loadImmediate(2.0); icg.move(r_i, icg.op(ADD, r_i, r_j));
icg.saveVariable(0, icg.op(ADD, r1, r2));
// j = a.b // j = a.b
icg.beginStatement(pos); icg.beginStatement(pos);
Register r4 = icg.loadName(world.identifiers[widenCString("a")]); r1 = icg.loadName(world.identifiers[widenCString("a")]);
Register r5 = icg.getProperty(r4, world.identifiers[widenCString("b")]); r1 = icg.getProperty(r1, world.identifiers[widenCString("b")]);
icg.saveVariable(1, r5); icg.move(r_j, r1);
// while (i) i = i + j; // while (i) i = i + j;
icg.beginWhileStatement(pos); icg.beginWhileStatement(pos);
r1 = icg.loadVariable(0); icg.endWhileExpression(r_i);
icg.endWhileExpression(r1); icg.move(r_i, icg.op(ADD, r_i, r_j));
icg.saveVariable(0, icg.op(ADD, icg.loadVariable(0), icg.loadVariable(1)));
icg.endWhileStatement(); icg.endWhileStatement();
// if (i) if (j) i = 3; else j = 4; // if (i) if (j) i = 3; else j = 4;
r1 = icg.loadVariable(0); icg.beginIfStatement(pos, r_i);
icg.beginIfStatement(pos, r1); icg.beginIfStatement(pos, r_j);
r2 = icg.loadVariable(1); icg.move(r_i, icg.loadImmediate(3));
icg.beginIfStatement(pos, r2);
icg.saveVariable(0, icg.loadImmediate(3));
icg.beginElseStatement(true); icg.beginElseStatement(true);
icg.saveVariable(1, icg.loadImmediate(4)); icg.move(r_j, icg.loadImmediate(4));
icg.endIfStatement(); icg.endIfStatement();
icg.beginElseStatement(false); icg.beginElseStatement(false);
icg.endIfStatement(); icg.endIfStatement();
// switch (i) { case 3: case 4: j = 4; break; case 5: j = 5; break; default : j = 6; } // switch (i) { case 3: case 4: j = 4; break; case 5: j = 5; break; default : j = 6; }
r1 = icg.loadVariable(0); icg.beginSwitchStatement(pos, r_i);
icg.beginSwitchStatement(pos, r1);
// case 3, note empty case statement (?necessary???) // case 3, note empty case statement (?necessary???)
icg.endCaseCondition(icg.loadImmediate(3)); icg.endCaseCondition(icg.loadImmediate(3));
icg.beginCaseStatement(); icg.beginCaseStatement();
@ -332,30 +331,29 @@ namespace JavaScript {
icg.endCaseCondition(icg.loadImmediate(4)); icg.endCaseCondition(icg.loadImmediate(4));
icg.beginCaseStatement(); icg.beginCaseStatement();
icg.beginStatement(pos); icg.beginStatement(pos);
icg.saveVariable(1, icg.loadImmediate(4)); icg.move(r_j, icg.loadImmediate(4));
icg.breakStatement(); icg.breakStatement();
icg.endCaseStatement(); icg.endCaseStatement();
// case 5 // case 5
icg.endCaseCondition(icg.loadImmediate(5)); icg.endCaseCondition(icg.loadImmediate(5));
icg.beginCaseStatement(); icg.beginCaseStatement();
icg.beginStatement(pos); icg.beginStatement(pos);
icg.saveVariable(1, icg.loadImmediate(5)); icg.move(r_j, icg.loadImmediate(5));
icg.breakStatement(); icg.breakStatement();
icg.endCaseStatement(); icg.endCaseStatement();
// default // default
icg.beginDefaultStatement(); icg.beginDefaultStatement();
icg.beginStatement(pos); icg.beginStatement(pos);
icg.saveVariable(1, icg.loadImmediate(6)); icg.move(r_j, icg.loadImmediate(6));
icg.endDefaultStatement(); icg.endDefaultStatement();
icg.endSwitchStatement(); icg.endSwitchStatement();
// for ( ; i; i + 1 ) j = 99; // for ( ; i; i = i + 1 ) j = 99;
icg.beginForStatement(pos); icg.beginForStatement(pos);
r1 = icg.loadVariable(0); icg.forCondition(r_i);
icg.forCondition(r1); icg.move(r_i, icg.op(ADD, r_i, icg.loadImmediate(1)));
icg.saveVariable(0, icg.op(ADD, icg.loadVariable(0), icg.loadImmediate(1)));
icg.forIncrement(); icg.forIncrement();
icg.saveVariable(0, icg.loadImmediate(99)); icg.move(r_j, icg.loadImmediate(99));
icg.endForStatement(); icg.endForStatement();
ICodeModule *icm = icg.complete(); ICodeModule *icm = icg.complete();
@ -374,11 +372,12 @@ namespace JavaScript {
ICodeGenerator fun; ICodeGenerator fun;
// function sum(n) { if (n > 1) return 1 + sum(n - 1); else return 1; } // function sum(n) { if (n > 1) return 1 + sum(n - 1); else return 1; }
// n is bound to var #0. // n is bound to var #0.
Register r_n = fun.allocateVariable(world.identifiers[widenCString("n")]);
fun.beginStatement(position); fun.beginStatement(position);
Register r1 = fun.op(COMPARE_GT, fun.loadVariable(0), fun.loadImmediate(1.0)); Register r1 = fun.op(COMPARE_GT, r_n, fun.loadImmediate(1.0));
fun.beginIfStatement(position, r1); fun.beginIfStatement(position, r1);
fun.beginStatement(position); fun.beginStatement(position);
r1 = fun.op(SUBTRACT, fun.loadVariable(0), fun.loadImmediate(1.0)); r1 = fun.op(SUBTRACT, r_n, fun.loadImmediate(1.0));
RegisterList args(1); RegisterList args(1);
args[0] = r1; args[0] = r1;
r1 = fun.call(fun.loadName(sum), args); r1 = fun.call(fun.loadName(sum), args);
@ -419,11 +418,12 @@ namespace JavaScript {
ICodeGenerator icg; ICodeGenerator icg;
// fact(n) { // fact(n) {
// n is bound to var #0.
// var result = 1; // var result = 1;
// result is bound to var #1. Register r_n = icg.allocateVariable(world.identifiers[widenCString("n")]);
Register r_result = icg.allocateVariable(world.identifiers[widenCString("result")]);
icg.beginStatement(position); icg.beginStatement(position);
icg.saveVariable(1, icg.loadImmediate(1.0)); icg.move(r_result, icg.loadImmediate(1.0));
// while (n > 1) { // while (n > 1) {
// result = result * n; // result = result * n;
@ -431,24 +431,20 @@ namespace JavaScript {
// } // }
{ {
icg.beginWhileStatement(position); icg.beginWhileStatement(position);
Register r0 = icg.loadVariable(0);
Register r1 = icg.loadImmediate(1.0); Register r1 = icg.loadImmediate(1.0);
Register r2 = icg.op(COMPARE_GT, r0, r1); Register r2 = icg.op(COMPARE_GT, r_n, r1);
icg.endWhileExpression(r2); icg.endWhileExpression(r2);
r0 = icg.loadVariable(0); r2 = icg.op(MULTIPLY, r_result, r_n);
r1 = icg.loadVariable(1); icg.move(r_result, r2);
r2 = icg.op(MULTIPLY, r1, r0);
icg.saveVariable(1, r2);
icg.beginStatement(position); icg.beginStatement(position);
r0 = icg.loadVariable(0);
r1 = icg.loadImmediate(1.0); r1 = icg.loadImmediate(1.0);
r2 = icg.op(SUBTRACT, r0, r1); r2 = icg.op(SUBTRACT, r_n, r1);
icg.saveVariable(0, r2); icg.move(r_n, r2);
icg.endWhileStatement(); icg.endWhileStatement();
} }
// return result; // return result;
icg.returnStatement(icg.loadVariable(1)); icg.returnStatement(r_result);
ICodeModule *icm = icg.complete(); ICodeModule *icm = icg.complete();
stdOut << icg; stdOut << icg;

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

@ -193,7 +193,7 @@ namespace JSTypes {
mLocals(iCode->itsMaxVariable + 1) mLocals(iCode->itsMaxVariable + 1)
{ {
// copy caller's parameter list in to locals. // copy caller's parameter list in to locals.
JSValues::iterator dest = mLocals.begin(); JSValues::iterator dest = mRegisters.begin();
const JSValues& params = caller->mRegisters; const JSValues& params = caller->mRegisters;
for (RegisterList::const_iterator src = list.begin(), for (RegisterList::const_iterator src = list.begin(),
end = list.end(); src != end; ++src, ++dest) { end = list.end(); src != end; ++src, ++dest) {
@ -225,9 +225,8 @@ namespace JSTypes {
// a stack of JSFrames. // a stack of JSFrames.
typedef std::stack<JSFrame*, std::vector<JSFrame*, gc_allocator<JSFrame*> > > JSFrameStack; typedef std::stack<JSFrame*, std::vector<JSFrame*, gc_allocator<JSFrame*> > > JSFrameStack;
} /* namespace JSTypes */ } /* namespace JSTypes */
}; /* namespace JavaScript */
} /* namespace JavaScript */
#endif /* jstypes_h */ #endif /* jstypes_h */

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

@ -129,8 +129,8 @@ namespace VM {
} }
ICodeOp getBranchOp() \ ICodeOp getBranchOp() \
{ return ((opcode >= COMPARE_LT) && (opcode <= COMPARE_GT)) ? \ { return ((opcode >= COMPARE_EQ) && (opcode <= COMPARE_NE)) ? \
(ICodeOp)(BRANCH_LT + (opcode - COMPARE_LT)) : NOP; } (ICodeOp)(BRANCH_EQ + (opcode - COMPARE_EQ)) : NOP; }
ICodeOp op() { return opcode; } ICodeOp op() { return opcode; }

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

@ -91,22 +91,6 @@ namespace ICG {
/********************************************************************/ /********************************************************************/
Register ICodeGenerator::loadVariable(uint32 frameIndex)
{
markMaxVariable(frameIndex);
Register dest = getRegister();
LoadVar *instr = new LoadVar(dest, frameIndex);
iCode->push_back(instr);
return dest;
}
void ICodeGenerator::saveVariable(uint32 frameIndex, Register value)
{
markMaxVariable(frameIndex);
SaveVar *instr = new SaveVar(frameIndex, value);
iCode->push_back(instr);
}
Register ICodeGenerator::loadImmediate(double value) Register ICodeGenerator::loadImmediate(double value)
{ {
Register dest = getRegister(); Register dest = getRegister();
@ -183,6 +167,12 @@ namespace ICG {
return dest; return dest;
} }
void ICodeGenerator::move(Register destination, Register source)
{
Move *instr = new Move(destination, source);
iCode->push_back(instr);
}
Register ICodeGenerator::op(ICodeOp op, Register source1, Register ICodeGenerator::op(ICodeOp op, Register source1,
Register source2) Register source2)
{ {
@ -638,4 +628,4 @@ namespace ICG {
} // namespace ICG } // namespace ICG
} // namespace JavaScript }; // namespace JavaScript

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

@ -107,10 +107,11 @@ namespace ICG {
{ if (variableIndex > maxVariable) maxVariable = variableIndex; } { if (variableIndex > maxVariable) maxVariable = variableIndex; }
Register topRegister; Register topRegister;
Register registerBase;
Register getRegister() \ Register getRegister() \
{ return topRegister++; } { return topRegister++; }
void resetTopRegister() \ void resetTopRegister() \
{ markMaxRegister(); topRegister = stitcher.empty() ? 0 : \ { markMaxRegister(); topRegister = stitcher.empty() ? registerBase : \
stitcher.back()->registerBase; } stitcher.back()->registerBase; }
ICodeOp getBranchOp() \ ICodeOp getBranchOp() \
@ -126,7 +127,7 @@ namespace ICG {
void branchConditional(Label *label, Register condition); void branchConditional(Label *label, Register condition);
public: public:
ICodeGenerator() : topRegister(0), maxRegister(0), ICodeGenerator() : topRegister(0), registerBase(0), maxRegister(0),
maxVariable(0) \ maxVariable(0) \
{ iCode = new InstructionStream(); } { iCode = new InstructionStream(); }
@ -135,12 +136,17 @@ namespace ICG {
void mergeStream(InstructionStream *sideStream); void mergeStream(InstructionStream *sideStream);
ICodeModule *complete(); ICodeModule *complete();
Register allocateVariable(StringAtom &name)
{ Register result = getRegister(); registerBase = topRegister; return result; }
Formatter& print(Formatter& f); Formatter& print(Formatter& f);
Register op(ICodeOp op, Register source); Register op(ICodeOp op, Register source);
Register op(ICodeOp op, Register source1, Register source2); Register op(ICodeOp op, Register source1, Register source2);
Register call(Register target, RegisterList args); Register call(Register target, RegisterList args);
void move(Register destination, Register source);
Register compare(ICodeOp op, Register source1, Register source2); Register compare(ICodeOp op, Register source1, Register source2);

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

@ -193,7 +193,7 @@ namespace JSTypes {
mLocals(iCode->itsMaxVariable + 1) mLocals(iCode->itsMaxVariable + 1)
{ {
// copy caller's parameter list in to locals. // copy caller's parameter list in to locals.
JSValues::iterator dest = mLocals.begin(); JSValues::iterator dest = mRegisters.begin();
const JSValues& params = caller->mRegisters; const JSValues& params = caller->mRegisters;
for (RegisterList::const_iterator src = list.begin(), for (RegisterList::const_iterator src = list.begin(),
end = list.end(); src != end; ++src, ++dest) { end = list.end(); src != end; ++src, ++dest) {
@ -225,9 +225,8 @@ namespace JSTypes {
// a stack of JSFrames. // a stack of JSFrames.
typedef std::stack<JSFrame*, std::vector<JSFrame*, gc_allocator<JSFrame*> > > JSFrameStack; typedef std::stack<JSFrame*, std::vector<JSFrame*, gc_allocator<JSFrame*> > > JSFrameStack;
} /* namespace JSTypes */ } /* namespace JSTypes */
}; /* namespace JavaScript */
} /* namespace JavaScript */
#endif /* jstypes_h */ #endif /* jstypes_h */

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

@ -129,8 +129,8 @@ namespace VM {
} }
ICodeOp getBranchOp() \ ICodeOp getBranchOp() \
{ return ((opcode >= COMPARE_LT) && (opcode <= COMPARE_GT)) ? \ { return ((opcode >= COMPARE_EQ) && (opcode <= COMPARE_NE)) ? \
(ICodeOp)(BRANCH_LT + (opcode - COMPARE_LT)) : NOP; } (ICodeOp)(BRANCH_EQ + (opcode - COMPARE_EQ)) : NOP; }
ICodeOp op() { return opcode; } ICodeOp op() { return opcode; }

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

@ -51,6 +51,7 @@ static void initConsole(StringPtr consoleName,
argc = 1; argc = 1;
argv = mac_argv; argv = mac_argv;
} }
#endif #endif
namespace JavaScript { namespace JavaScript {
@ -287,43 +288,41 @@ namespace JavaScript {
uint32 pos = 0; uint32 pos = 0;
ICodeGenerator icg; ICodeGenerator icg;
// var i,j; i = j + 2; // var i,j;
// i is bound to var #0, j to var #1 // i is bound to var #0, j to var #1
Register r_i = icg.allocateVariable(world.identifiers[widenCString("i")]);
Register r_j = icg.allocateVariable(world.identifiers[widenCString("j")]);
// i = j + 2;
icg.beginStatement(pos); icg.beginStatement(pos);
Register r1 = icg.loadVariable(1); Register r1 = icg.loadImmediate(2.0);
Register r2 = icg.loadImmediate(2.0); icg.move(r_i, icg.op(ADD, r_i, r_j));
icg.saveVariable(0, icg.op(ADD, r1, r2));
// j = a.b // j = a.b
icg.beginStatement(pos); icg.beginStatement(pos);
Register r4 = icg.loadName(world.identifiers[widenCString("a")]); r1 = icg.loadName(world.identifiers[widenCString("a")]);
Register r5 = icg.getProperty(r4, world.identifiers[widenCString("b")]); r1 = icg.getProperty(r1, world.identifiers[widenCString("b")]);
icg.saveVariable(1, r5); icg.move(r_j, r1);
// while (i) i = i + j; // while (i) i = i + j;
icg.beginWhileStatement(pos); icg.beginWhileStatement(pos);
r1 = icg.loadVariable(0); icg.endWhileExpression(r_i);
icg.endWhileExpression(r1); icg.move(r_i, icg.op(ADD, r_i, r_j));
icg.saveVariable(0, icg.op(ADD, icg.loadVariable(0), icg.loadVariable(1)));
icg.endWhileStatement(); icg.endWhileStatement();
// if (i) if (j) i = 3; else j = 4; // if (i) if (j) i = 3; else j = 4;
r1 = icg.loadVariable(0); icg.beginIfStatement(pos, r_i);
icg.beginIfStatement(pos, r1); icg.beginIfStatement(pos, r_j);
r2 = icg.loadVariable(1); icg.move(r_i, icg.loadImmediate(3));
icg.beginIfStatement(pos, r2);
icg.saveVariable(0, icg.loadImmediate(3));
icg.beginElseStatement(true); icg.beginElseStatement(true);
icg.saveVariable(1, icg.loadImmediate(4)); icg.move(r_j, icg.loadImmediate(4));
icg.endIfStatement(); icg.endIfStatement();
icg.beginElseStatement(false); icg.beginElseStatement(false);
icg.endIfStatement(); icg.endIfStatement();
// switch (i) { case 3: case 4: j = 4; break; case 5: j = 5; break; default : j = 6; } // switch (i) { case 3: case 4: j = 4; break; case 5: j = 5; break; default : j = 6; }
r1 = icg.loadVariable(0); icg.beginSwitchStatement(pos, r_i);
icg.beginSwitchStatement(pos, r1);
// case 3, note empty case statement (?necessary???) // case 3, note empty case statement (?necessary???)
icg.endCaseCondition(icg.loadImmediate(3)); icg.endCaseCondition(icg.loadImmediate(3));
icg.beginCaseStatement(); icg.beginCaseStatement();
@ -332,30 +331,29 @@ namespace JavaScript {
icg.endCaseCondition(icg.loadImmediate(4)); icg.endCaseCondition(icg.loadImmediate(4));
icg.beginCaseStatement(); icg.beginCaseStatement();
icg.beginStatement(pos); icg.beginStatement(pos);
icg.saveVariable(1, icg.loadImmediate(4)); icg.move(r_j, icg.loadImmediate(4));
icg.breakStatement(); icg.breakStatement();
icg.endCaseStatement(); icg.endCaseStatement();
// case 5 // case 5
icg.endCaseCondition(icg.loadImmediate(5)); icg.endCaseCondition(icg.loadImmediate(5));
icg.beginCaseStatement(); icg.beginCaseStatement();
icg.beginStatement(pos); icg.beginStatement(pos);
icg.saveVariable(1, icg.loadImmediate(5)); icg.move(r_j, icg.loadImmediate(5));
icg.breakStatement(); icg.breakStatement();
icg.endCaseStatement(); icg.endCaseStatement();
// default // default
icg.beginDefaultStatement(); icg.beginDefaultStatement();
icg.beginStatement(pos); icg.beginStatement(pos);
icg.saveVariable(1, icg.loadImmediate(6)); icg.move(r_j, icg.loadImmediate(6));
icg.endDefaultStatement(); icg.endDefaultStatement();
icg.endSwitchStatement(); icg.endSwitchStatement();
// for ( ; i; i + 1 ) j = 99; // for ( ; i; i = i + 1 ) j = 99;
icg.beginForStatement(pos); icg.beginForStatement(pos);
r1 = icg.loadVariable(0); icg.forCondition(r_i);
icg.forCondition(r1); icg.move(r_i, icg.op(ADD, r_i, icg.loadImmediate(1)));
icg.saveVariable(0, icg.op(ADD, icg.loadVariable(0), icg.loadImmediate(1)));
icg.forIncrement(); icg.forIncrement();
icg.saveVariable(0, icg.loadImmediate(99)); icg.move(r_j, icg.loadImmediate(99));
icg.endForStatement(); icg.endForStatement();
ICodeModule *icm = icg.complete(); ICodeModule *icm = icg.complete();
@ -374,11 +372,12 @@ namespace JavaScript {
ICodeGenerator fun; ICodeGenerator fun;
// function sum(n) { if (n > 1) return 1 + sum(n - 1); else return 1; } // function sum(n) { if (n > 1) return 1 + sum(n - 1); else return 1; }
// n is bound to var #0. // n is bound to var #0.
Register r_n = fun.allocateVariable(world.identifiers[widenCString("n")]);
fun.beginStatement(position); fun.beginStatement(position);
Register r1 = fun.op(COMPARE_GT, fun.loadVariable(0), fun.loadImmediate(1.0)); Register r1 = fun.op(COMPARE_GT, r_n, fun.loadImmediate(1.0));
fun.beginIfStatement(position, r1); fun.beginIfStatement(position, r1);
fun.beginStatement(position); fun.beginStatement(position);
r1 = fun.op(SUBTRACT, fun.loadVariable(0), fun.loadImmediate(1.0)); r1 = fun.op(SUBTRACT, r_n, fun.loadImmediate(1.0));
RegisterList args(1); RegisterList args(1);
args[0] = r1; args[0] = r1;
r1 = fun.call(fun.loadName(sum), args); r1 = fun.call(fun.loadName(sum), args);
@ -419,11 +418,12 @@ namespace JavaScript {
ICodeGenerator icg; ICodeGenerator icg;
// fact(n) { // fact(n) {
// n is bound to var #0.
// var result = 1; // var result = 1;
// result is bound to var #1. Register r_n = icg.allocateVariable(world.identifiers[widenCString("n")]);
Register r_result = icg.allocateVariable(world.identifiers[widenCString("result")]);
icg.beginStatement(position); icg.beginStatement(position);
icg.saveVariable(1, icg.loadImmediate(1.0)); icg.move(r_result, icg.loadImmediate(1.0));
// while (n > 1) { // while (n > 1) {
// result = result * n; // result = result * n;
@ -431,24 +431,20 @@ namespace JavaScript {
// } // }
{ {
icg.beginWhileStatement(position); icg.beginWhileStatement(position);
Register r0 = icg.loadVariable(0);
Register r1 = icg.loadImmediate(1.0); Register r1 = icg.loadImmediate(1.0);
Register r2 = icg.op(COMPARE_GT, r0, r1); Register r2 = icg.op(COMPARE_GT, r_n, r1);
icg.endWhileExpression(r2); icg.endWhileExpression(r2);
r0 = icg.loadVariable(0); r2 = icg.op(MULTIPLY, r_result, r_n);
r1 = icg.loadVariable(1); icg.move(r_result, r2);
r2 = icg.op(MULTIPLY, r1, r0);
icg.saveVariable(1, r2);
icg.beginStatement(position); icg.beginStatement(position);
r0 = icg.loadVariable(0);
r1 = icg.loadImmediate(1.0); r1 = icg.loadImmediate(1.0);
r2 = icg.op(SUBTRACT, r0, r1); r2 = icg.op(SUBTRACT, r_n, r1);
icg.saveVariable(0, r2); icg.move(r_n, r2);
icg.endWhileStatement(); icg.endWhileStatement();
} }
// return result; // return result;
icg.returnStatement(icg.loadVariable(1)); icg.returnStatement(r_result);
ICodeModule *icm = icg.complete(); ICodeModule *icm = icg.complete();
stdOut << icg; stdOut << icg;