Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #3

Merged
merged 15 commits into from
Aug 18, 2016
73 changes: 42 additions & 31 deletions grammar.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,46 @@ keyword_constant:
true
| false
| null

factor:

variable:
ID
| "(" expression ")"
| lambda_decl

variable_suffix:
variable { ( "[" expression "]" | "(" expression_list ")" | "." ID )}

value:
INT_CONST
| CHAR_CONST
| STRING_CONST
| keyword_constant
| ID
| "(" expression ")"
| "[" expression_list "]"
| function_decl
| table_decl
| variable_suffix

positive_factor:
factor { ( [ "[" expression "]" ] | [ "(" expression_list ")" ] ) }

not_factor:
[ "!" ] positive_factor
not_expr:
[ "!" ] value

term:
[ "-" ] not_factor
neg_expr:
[ "-" ] not_expr

additive_expression:
term { ( "*" | "/" ) term }
mul_and_div_expr:
neg_expr { ( "*" | "/" ) neg_expr }

relational_expression:
additive_expression { ( "+" | "-" ) additive_expression }
add_and_sub_expr:
mul_and_div_expr { ( "+" | "-" ) mul_and_div_expr }

and_expression:
relational_expression [ ( "<" | ">" | ">=" | "<=" | "==" | "!=" ) relational_expression ]
real_expr:
add_and_sub_expr [add_and_sub_expr ]

or_expression:
and_expression { "&&" and_expression }
and_expr:
real_expr { ( "<" | ">" | ">=" | "<=" | "==" | "!=" ) real_expr }

expression:
or_expression { "||" or_expression }

assign_expression:
expression { "=" expression }
or_expr:
and_expr { "&" and_expr }

var_decl:
"let" ID "=" assign_expression ";"
expression:
or_expr { "|" or_expr }

expression_list:
expression { "," expression }
Expand All @@ -54,8 +54,8 @@ statement:
| "return" [ assign_expression ] ";"
| "break" ";"
| "continue" ";"
| assign_expression ";"
| var_decl
| expression ";"
| decl

block:
"{" { statement } "}"
Expand All @@ -66,9 +66,20 @@ param_list:
function_decl:
"function" "(" [ param_list ] ")" block

variable_decl:
define_decl
| let_decl

define_decl:
"define" ID "=" expression

let_decl:
"let" ID "=" expression

decl:
variable_decl
| function_decl

program:
{ ( define_decl | statement ) }
{ ( decl | expression ) }
```
198 changes: 174 additions & 24 deletions script/IR/CFG.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
#include "CFG.h"
#include "CFG.h"

#include "Instruction.h"
#include "IRContext.h"

#include <map>
#include <list>
#include <functional>
#include <algorithm>
#include <cassert>
#include <sstream>

using script::ir::Instruction;
using namespace script::ir;

namespace script
{
BasicBlock * CFG::createBasicBlock(std::string name)
BasicBlock * CFG::createBasicBlock(const std::string &name)
{
BasicBlock *temp = new BasicBlock(numBlockIDs_++, name);
blocks_.push_back(temp);
Expand All @@ -20,21 +23,153 @@ namespace script

void CFG::setEntry(BasicBlock * entry)
{
assert(entry != nullptr);
start_ = entry;
}

void CFG::setEnd(BasicBlock * end)
{
assert(end != nullptr);
end_ = end;
}

BasicBlock * CFG::getEntryBlock()
{
return start_;
}

IRContext * CFG::getContext()
{
return context_;
}

void CFG::sealOthersBlock()
{
for (auto *block : blocks_)
sealBlock(block);
}

void CFG::sealBlock(BasicBlock * block)
{
assert(block != nullptr);
if (sealedBlock_.count(block) != 0)
return;

auto &block2Phi = incompletePhis_[block];
for (auto &b2p : block2Phi)
{
addPhiOperands(b2p.first, (Phi*)b2p.second);
}
sealedBlock_.insert(block);
}

void CFG::saveVariableDef(std::string name, BasicBlock * block, Value * value)
{
assert(block != nullptr && value != nullptr);
currentDef_[name][block] = value;
}

Value * CFG::readVariableDef(std::string name, BasicBlock * block)
{
assert(block != nullptr);
auto &def = currentDef_[name];
if (def.find(block) != def.end())
return def[block];
return readVariableRecurisive(name, block);
}

std::string CFG::phiName(std::string & name)
{
std::stringstream stream;
stream << name << '.' << phiCounts_[name]++;
std::string tmp;
stream >> tmp;
return tmp;
}

Value * CFG::readVariableRecurisive(std::string name, BasicBlock * block)
{
assert(block != nullptr);
Value *val = nullptr;
if (sealedBlock_.find(block) == sealedBlock_.end())
{
// incomplete CFGs.
val = context_->createAtBegin<Phi>(block, phiName(name));
incompletePhis_[block][name] = val;
}
else if (block->numOfPrecursors() == 1)
{
// Optimize the common case of one predecessor, no Phi needed.
val = readVariableDef(name, block->precursor(0));
}
else
{
// Break potential cycles with operandless Phi
val = context_->createAtBegin<Phi>(block, phiName(name));
saveVariableDef(name, block, val);
val = addPhiOperands(name, (Phi*)val);
}
saveVariableDef(name, block, val);
return val;
}

ir::Value * CFG::addPhiOperands(std::string name, ir::Phi * phi)
{
// Determine operands from predecessors
BasicBlock *phiParent = phi->getParent();
for (auto i = phiParent->precursor_begin(),
e = phiParent->precursor_end();
i != e; ++i)
{
phi->appendOperand(readVariableDef(name, *i));
}
return tryRemoveTrivialPhi(phi);
}

ir::Value * CFG::tryRemoveTrivialPhi(ir::Phi * phi)
{
Value *same = nullptr;
for (auto beg = phi->op_begin(); beg != phi->op_end(); beg++)
{
Value *op = beg->getValue();
if (op == same || op == phi)
// Unique value or self−reference
continue;
if (same != nullptr)
// The phi merges at least two values : not trivial
return phi;
same = op;
}
if (same == nullptr)
same = context_->create<Undef>(phi->name());
// try all users except the phi itself.
// Try to recursively remove all phi users,
// which might have become trivial
for (auto iter = phi->use_begin(); iter != phi->use_end(); ++iter)
{
if (iter->getUser() != phi)
{
Value *user = iter->getUser();
if (user->instance() == Instructions::IR_Phi)
tryRemoveTrivialPhi((Phi*)user);
}
}
// Reroute all uses of phi to same and remove phi
phi->replaceBy(same);
return same;
}

CFG::CFG()
: numBlockIDs_(0), start_(nullptr), end_(nullptr)
: context_(new IRContext()), numBlockIDs_(0)
, start_(nullptr), end_(nullptr)
{
}

CFG::~CFG()
{
if (context_ != nullptr)
delete context_;

for (auto &i : blocks_)
{
delete i;
Expand All @@ -52,30 +187,45 @@ namespace script
successors_.push_back(block);
}

void BasicBlock::push(Instruction * instr)
BasicBlock * BasicBlock::precursor(int idx)
{
if (head_ == nullptr)
{
end_ = head_ = instr;
}
else
{
end_->next_ = instr;
instr->prev_ = end_;
instr->next_ = nullptr;
end_ = instr;
}
if (idx < numOfPrecursors())
return precursors_[idx];
return nullptr;
}

void BasicBlock::unique()
BasicBlock * BasicBlock::successor(int idx)
{
precursors_.sort();
auto end_unique = std::unique(precursors_.begin(), precursors_.end());
precursors_.erase(end_unique, precursors_.end());

successors_.sort();
end_unique = std::unique(successors_.begin(), successors_.end());
precursors_.erase(end_unique, successors_.end());
if (idx < numOfSuccessors())
return successors_[idx];
return nullptr;
}

void BasicBlock::push_back(Instruction * instr)
{
assert(instr != nullptr);
instrs_.push_back(instr);
}

void BasicBlock::push_front(Instruction * instr)
{
assert(instr != nullptr);
instrs_.push_front(instr);
}

void BasicBlock::pop_back()
{
instrs_.pop_back();
}

void BasicBlock::pop_front()
{
instrs_.pop_front();
}

void BasicBlock::erase(Instruction * instr)
{
instrs_.remove(instr);
}
}

Loading