| Index: src/cfg.cc
|
| ===================================================================
|
| --- src/cfg.cc (revision 2620)
|
| +++ src/cfg.cc (working copy)
|
| @@ -42,8 +42,10 @@
|
| CfgGlobals::CfgGlobals(FunctionLiteral* fun)
|
| : global_fun_(fun),
|
| global_exit_(new ExitNode()),
|
| + effect_(new Effect()),
|
| #ifdef DEBUG
|
| node_counter_(0),
|
| + temp_counter_(0),
|
| #endif
|
| previous_(top_) {
|
| top_ = this;
|
| @@ -73,6 +75,9 @@
|
| if (cfg == NULL) {
|
| BAILOUT("unsupported statement type");
|
| }
|
| + if (cfg->is_empty()) {
|
| + BAILOUT("function body produces empty cfg");
|
| + }
|
| if (cfg->has_exit()) {
|
| BAILOUT("control path without explicit return");
|
| }
|
| @@ -90,8 +95,10 @@
|
|
|
|
|
| void Cfg::Append(Instruction* instr) {
|
| - ASSERT(has_exit());
|
| - ASSERT(!is_empty());
|
| + ASSERT(is_empty() || has_exit());
|
| + if (is_empty()) {
|
| + entry_ = exit_ = new InstructionBlock();
|
| + }
|
| InstructionBlock::cast(exit_)->Append(instr);
|
| }
|
|
|
| @@ -104,6 +111,27 @@
|
| }
|
|
|
|
|
| +void Cfg::Concatenate(Cfg* other) {
|
| + ASSERT(is_empty() || has_exit());
|
| + if (other->is_empty()) return;
|
| +
|
| + if (is_empty()) {
|
| + entry_ = other->entry();
|
| + exit_ = other->exit();
|
| + } else {
|
| + // We have a pair of nonempty fragments and this has an available exit.
|
| + // Destructively glue the fragments together.
|
| + InstructionBlock* first = InstructionBlock::cast(exit_);
|
| + InstructionBlock* second = InstructionBlock::cast(other->entry());
|
| + first->instructions()->AddAll(*second->instructions());
|
| + if (second->successor() != NULL) {
|
| + first->set_successor(second->successor());
|
| + exit_ = other->exit();
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| void InstructionBlock::Unmark() {
|
| if (is_marked_) {
|
| is_marked_ = false;
|
| @@ -166,6 +194,26 @@
|
| }
|
|
|
|
|
| +void BinaryOpInstr::FastAllocate(TempLocation* temp) {
|
| + ASSERT(temp->where() == TempLocation::NOWHERE);
|
| + if (temp == val0_ || temp == val1_) {
|
| + temp->set_where(TempLocation::ACCUMULATOR);
|
| + } else {
|
| + temp->set_where(TempLocation::STACK);
|
| + }
|
| +}
|
| +
|
| +
|
| +void ReturnInstr::FastAllocate(TempLocation* temp) {
|
| + ASSERT(temp->where() == TempLocation::NOWHERE);
|
| + if (temp == value_) {
|
| + temp->set_where(TempLocation::ACCUMULATOR);
|
| + } else {
|
| + temp->set_where(TempLocation::STACK);
|
| + }
|
| +}
|
| +
|
| +
|
| // The expression builder should not be used for declarations or statements.
|
| void ExpressionBuilder::VisitDeclaration(Declaration* decl) { UNREACHABLE(); }
|
|
|
| @@ -178,13 +226,10 @@
|
| // Macros (temporarily) handling unsupported expression types.
|
| #define BAILOUT(reason) \
|
| do { \
|
| - value_ = NULL; \
|
| + cfg_ = NULL; \
|
| return; \
|
| } while (false)
|
|
|
| -#define CHECK_BAILOUT() \
|
| - if (value_ == NULL) { return; } else {}
|
| -
|
| void ExpressionBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
|
| BAILOUT("FunctionLiteral");
|
| }
|
| @@ -290,7 +335,46 @@
|
|
|
|
|
| void ExpressionBuilder::VisitBinaryOperation(BinaryOperation* expr) {
|
| - BAILOUT("BinaryOperation");
|
| + Token::Value op = expr->op();
|
| + switch (op) {
|
| + case Token::COMMA:
|
| + case Token::OR:
|
| + case Token::AND:
|
| + BAILOUT("unsupported binary operation");
|
| +
|
| + case Token::BIT_OR:
|
| + case Token::BIT_XOR:
|
| + case Token::BIT_AND:
|
| + case Token::SHL:
|
| + case Token::SAR:
|
| + case Token::SHR:
|
| + case Token::ADD:
|
| + case Token::SUB:
|
| + case Token::MUL:
|
| + case Token::DIV:
|
| + case Token::MOD: {
|
| + ExpressionBuilder left, right;
|
| + left.Build(expr->left());
|
| + if (left.cfg() == NULL) {
|
| + BAILOUT("unsupported left subexpression in binop");
|
| + }
|
| + right.Build(expr->right());
|
| + if (right.cfg() == NULL) {
|
| + BAILOUT("unsupported right subexpression in binop");
|
| + }
|
| +
|
| + Location* temp = new TempLocation();
|
| + cfg_ = left.cfg();
|
| + cfg_->Concatenate(right.cfg());
|
| + cfg_->Append(new BinaryOpInstr(temp, op, left.value(), right.value()));
|
| +
|
| + value_ = temp;
|
| + return;
|
| + }
|
| +
|
| + default:
|
| + UNREACHABLE();
|
| + }
|
| }
|
|
|
|
|
| @@ -304,7 +388,6 @@
|
| }
|
|
|
| #undef BAILOUT
|
| -#undef CHECK_BAILOUT
|
|
|
|
|
| // Macros (temporarily) handling unsupported statement types.
|
| @@ -367,10 +450,13 @@
|
|
|
| void StatementBuilder::VisitReturnStatement(ReturnStatement* stmt) {
|
| ExpressionBuilder builder;
|
| - builder.Visit(stmt->expression());
|
| - Value* value = builder.value();
|
| - if (value == NULL) BAILOUT("unsupported expression type");
|
| - cfg_->AppendReturnInstruction(value);
|
| + builder.Build(stmt->expression());
|
| + if (builder.cfg() == NULL) {
|
| + BAILOUT("unsupported expression in return statement");
|
| + }
|
| +
|
| + cfg_->Concatenate(builder.cfg());
|
| + cfg_->AppendReturnInstruction(builder.value());
|
| }
|
|
|
|
|
| @@ -430,6 +516,11 @@
|
| }
|
|
|
|
|
| +void Effect::Print() {
|
| + PrintF("Effect");
|
| +}
|
| +
|
| +
|
| void SlotLocation::Print() {
|
| PrintF("Slot(");
|
| switch (type_) {
|
| @@ -445,10 +536,26 @@
|
| }
|
|
|
|
|
| +void TempLocation::Print() {
|
| + PrintF("Temp(%d)", number());
|
| +}
|
| +
|
| +
|
| +void BinaryOpInstr::Print() {
|
| + PrintF("BinaryOp(");
|
| + loc_->Print();
|
| + PrintF(", %s, ", Token::Name(op_));
|
| + val0_->Print();
|
| + PrintF(", ");
|
| + val1_->Print();
|
| + PrintF(")\n");
|
| +}
|
| +
|
| +
|
| void ReturnInstr::Print() {
|
| - PrintF("Return ");
|
| + PrintF("Return(");
|
| value_->Print();
|
| - PrintF("\n");
|
| + PrintF(")\n");
|
| }
|
|
|
|
|
|
|