2 #include <boost/foreach.hpp>
4 #include <ozulis/core/assert.hh>
5 #include <ozulis/ast/cast-tables.hh>
6 #include <ozulis/ast/ast-cast.hh>
7 #include <ozulis/ast/node-factory.hh>
8 #include <ozulis/ast/scope.hh>
9 #include <ozulis/visitors/type-checker.hh>
10 #include <ozulis/visitors/simplify.hh>
11 #include <ozulis/visitors/browser.hh>
22 * <b>Algorithm</b><br>
24 * - for every instruction
25 * - split the instruction in 3 address instruction
29 : Visitor
<Simplify
>(),
42 Simplify::simplify(ast::Exp
*& node
)
55 ss
<< "$" << ++nextId_
;
60 Simplify::currentId() const
68 Simplify::makeTmpResult(ast::Exp
& node
)
70 if (node
.type
->nodeType
== ast::VoidType::nodeTypeId())
73 simplifications
.push_back(&node
);
77 ast::SymbolExp
* sexp
= new ast::SymbolExp();
78 sexp
->symbol
= new ast::Symbol
;
79 sexp
->symbol
->name
= nextId();
80 sexp
->symbol
->type
= node
.type
;
81 sexp
->type
= node
.type
;
82 ast::RegisterAddress
* addr
= new ast::RegisterAddress
;
83 addr
->address
= scope
->prefix
+ sexp
->symbol
->name
;
84 sexp
->symbol
->address
= addr
;
86 ast::AssignExp
* assign
= new ast::AssignExp();
87 assign
->value
= &node
;
89 assign
->type
= node
.type
;
90 simplifications
.push_back(assign
);
95 static void visitBlock(ast::Node
& node_
, Simplify
& ctx
)
97 ast::Block
& block
= reinterpret_cast<ast::Block
&> (node_
);
98 ctx
.scope
= block
.scope
;
99 std::vector
<ast::Node
*> backup
= ctx
.simplifications
;
100 ctx
.simplifications
.clear();
102 BOOST_FOREACH (ast::Node
* node
, (*block
.statements
))
105 Simplify::visit(*node
, ctx
);
108 *block
.statements
= ctx
.simplifications
;
109 ctx
.simplifications
= backup
;
112 static void visitVoidExp(ast::Node
& node_
, Simplify
& ctx
)
114 ast::VoidExp
& node
= reinterpret_cast<ast::VoidExp
&> (node_
);
115 ctx
.replacement
= &node
;
118 #define SIMPLIFY_UNARY_EXP(Type) \
121 * - Simplify childs \
122 * - Create a new id. \
123 * - Create a new assign exp to id. \
124 * - Create a IdExp and tell replace the parent's child with it. \
126 static void visit##Type(ast::Node & node_, Simplify & ctx) \
128 ast::Type & node = reinterpret_cast<ast::Type &> (node_); \
130 ctx.simplify(node.exp); \
132 ctx.makeTmpResult(node); \
135 SIMPLIFY_UNARY_EXP(NotExp
)
136 SIMPLIFY_UNARY_EXP(BangExp
)
137 SIMPLIFY_UNARY_EXP(NegExp
)
139 #define SIMPLIFY_BINARY_EXP(Type) \
142 * - Simplify childs \
143 * - Create a new id. \
144 * - Create a new assign exp to id. \
145 * - Create a IdExp and tell replace the parent's child with it. \
147 static void visit##Type(ast::Node & node_, Simplify & ctx) \
149 ast::Type & node = reinterpret_cast<ast::Type &> (node_); \
150 ctx.simplify(node.left); \
151 ctx.simplify(node.right); \
153 ctx.makeTmpResult(node); \
156 SIMPLIFY_BINARY_EXP(EqExp
)
157 SIMPLIFY_BINARY_EXP(NeqExp
)
158 SIMPLIFY_BINARY_EXP(LtExp
)
159 SIMPLIFY_BINARY_EXP(LtEqExp
)
160 SIMPLIFY_BINARY_EXP(GtExp
)
161 SIMPLIFY_BINARY_EXP(GtEqExp
)
163 SIMPLIFY_BINARY_EXP(AddExp
)
164 SIMPLIFY_BINARY_EXP(SubExp
)
165 SIMPLIFY_BINARY_EXP(MulExp
)
166 SIMPLIFY_BINARY_EXP(DivExp
)
167 SIMPLIFY_BINARY_EXP(ModExp
)
169 SIMPLIFY_BINARY_EXP(AndExp
)
170 SIMPLIFY_BINARY_EXP(OrExp
)
171 SIMPLIFY_BINARY_EXP(XorExp
)
173 SIMPLIFY_BINARY_EXP(AndAndExp
)
174 SIMPLIFY_BINARY_EXP(OrOrExp
)
176 SIMPLIFY_BINARY_EXP(ShlExp
)
177 SIMPLIFY_BINARY_EXP(AShrExp
)
178 SIMPLIFY_BINARY_EXP(LShrExp
)
181 static void visitAssignExp(ast::Node
& node_
, Simplify
& ctx
)
183 ast::AssignExp
& node
= reinterpret_cast<ast::AssignExp
&> (node_
);
188 ctx
.simplifyLValue(node
.dest
);
189 ctx
.simplify(node
.value
);
191 ast::SymbolExp
* dest
= ast::ast_cast
<ast::SymbolExp
*> (node
.dest
);
192 ast::StoreVar
* sv
= new ast::StoreVar();
193 sv
->name
= dest
->symbol
->name
;
194 sv
->value
= ctx
.replacement
; // node.value
195 ctx
.simplifications
.push_back(sv
);
199 static void visitNumberExp(ast::Node
& node_
, Simplify
& ctx
)
201 ast::NumberExp
& node
= reinterpret_cast<ast::NumberExp
&> (node_
);
202 ctx
.replacement
= &node
;
205 #define BAD_NODE(Type) \
206 static void visit##Type(ast::Node & /*node_*/, \
207 Simplify & /*ctx*/) \
209 assert_msg(false, "should never get here."); \
216 /** @internal load a symbol if it's in memory */
217 static void visitSymbolExp(ast::Node
& node_
, Simplify
& ctx
)
219 ast::SymbolExp
& node
= reinterpret_cast<ast::SymbolExp
&> (node_
);
220 if (node
.symbol
->address
->nodeType
== ast::MemoryAddress::nodeTypeId())
222 ast::SymbolExp
* sexp
= new ast::SymbolExp
;
223 sexp
->symbol
= new ast::Symbol
;
224 sexp
->symbol
->name
= node
.symbol
->name
+ "_" + ctx
.nextId();;
225 sexp
->symbol
->type
= unreferencedType(node
.type
);
226 sexp
->symbol
->address
= new ast::RegisterAddress
;
227 sexp
->type
= sexp
->symbol
->type
;
228 ctx
.replacement
= sexp
;
230 ast::LoadVar
* lv
= new ast::LoadVar
;
231 lv
->to
= sexp
->symbol
->name
;
233 ctx
.simplifications
.push_back(lv
);
236 ctx
.replacement
= &node
;
239 static void visitAtExp(ast::Node
& node_
, Simplify
& ctx
)
241 ast::AtExp
& node
= reinterpret_cast<ast::AtExp
&> (node_
);
242 ctx
.replacement
= &node
;
243 ctx
.simplifyLValue(ctx
.replacement
);
246 static void visitDereferenceExp(ast::Node
& node_
, Simplify
& ctx
)
248 ast::DereferenceExp
& node
= reinterpret_cast<ast::DereferenceExp
&> (node_
);
249 ctx
.simplify(node
.exp
);
251 ast::LoadVar
* lv
= new ast::LoadVar
;
252 lv
->to
= ctx
.nextId();
254 ctx
.simplifications
.push_back(lv
);
256 ast::SymbolExp
* id
= new ast::SymbolExp
;
257 id
->symbol
= new ast::Symbol
;
258 id
->symbol
->name
= lv
->to
;
259 id
->symbol
->type
= node
.type
;
260 id
->symbol
->address
= new ast::RegisterAddress
;
261 id
->type
= node
.type
;
262 ctx
.replacement
= id
;
265 /** @internal just do (node.exp + node.index)* */
266 static void visitDereferenceByIndexExp(ast::Node
& node_
, Simplify
& ctx
)
268 ast::DereferenceByIndexExp
& node
=
269 reinterpret_cast<ast::DereferenceByIndexExp
&> (node_
);
270 ast::PointerArithExp
* add
= new ast::PointerArithExp
;
271 add
->pointer
= node
.exp
;
272 add
->offset
= node
.index
;
274 ast::DereferenceExp
* deref
= new ast::DereferenceExp
;
276 ast::Exp
* tmp
= deref
;
282 ctx
.replacement
= tmp
;
285 static void visitCallExp(ast::Node
& node_
, Simplify
& ctx
)
287 ast::CallExp
& node
= reinterpret_cast<ast::CallExp
&> (node_
);
288 BOOST_FOREACH (ast::Exp
*& exp
, (*node
.args
))
291 ctx
.makeTmpResult(node
);
294 /** @internal develop the cast, and simplify it */
295 static void visitCastExp(ast::Node
& node_
, Simplify
& ctx
)
297 ast::CastExp
& node
= reinterpret_cast<ast::CastExp
&> (node_
);
298 ctx
.simplify(node
.exp
);
301 // The cast exp is dummy, remove it
302 if (!castToBestType(node
.type
, node
.exp
->type
))
305 ctx
.makeTmpResult(node
);
308 static void visitLabel(ast::Node
& node_
, Simplify
& ctx
)
310 ast::Label
& node
= reinterpret_cast<ast::Label
&> (node_
);
311 ctx
.simplifications
.push_back(&node
);
314 static void visitGoto(ast::Node
& node_
, Simplify
& ctx
)
316 ast::Goto
& node
= reinterpret_cast<ast::Goto
&> (node_
);
317 ctx
.simplifications
.push_back(&node
);
320 static void visitReturn(ast::Node
& node_
, Simplify
& ctx
)
322 ast::Return
& node
= reinterpret_cast<ast::Return
&> (node_
);
323 ctx
.simplify(node
.exp
);
324 ctx
.simplifications
.push_back(&node
);
338 static void visitIf(ast::Node
& node_
, Simplify
& ctx
)
340 ast::If
& node
= reinterpret_cast<ast::If
&> (node_
);
341 ctx
.simplify(node
.branch
->cond
);
342 ctx
.simplifications
.push_back(node
.branch
);
344 node
.branch
->trueLabel
= new ast::Label
;
345 node
.branch
->trueLabel
->name
= std::string("if_true_") + ctx
.nextId();
346 node
.branch
->falseLabel
= new ast::Label
;
347 node
.branch
->falseLabel
->name
= std::string("if_false_") + ctx
.nextId();
348 node
.endLabel
= new ast::Label
;
349 node
.endLabel
->name
= std::string("if_end_") + ctx
.nextId();
351 ctx
.simplifications
.push_back(node
.branch
->trueLabel
);
352 Simplify::visit(*node
.trueBlock
, ctx
);
353 ast::Goto
* gotoNode
= new ast::Goto
;
354 gotoNode
->label
= node
.endLabel
->name
;
356 ctx
.simplifications
.push_back(node
.branch
->falseLabel
);
357 Simplify::visit(*node
.falseBlock
, ctx
);
358 ctx
.simplifications
.push_back(node
.endLabel
);
371 static void visitWhile(ast::Node
& node_
, Simplify
& ctx
)
373 ast::While
& node
= reinterpret_cast<ast::While
&> (node_
);
375 assert(node
.branch
->cond
);
377 node
.beginLabel
= new ast::Label
;
378 node
.beginLabel
->name
= std::string("do_while_1_") + ctx
.nextId();
379 node
.branch
->trueLabel
= new ast::Label
;
380 node
.branch
->trueLabel
->name
= std::string("do_while_2_") + ctx
.nextId();
381 node
.branch
->falseLabel
= new ast::Label
;
382 node
.branch
->falseLabel
->name
= std::string("do_while_3_") + ctx
.nextId();
384 ctx
.simplifications
.push_back(node
.beginLabel
);
385 ctx
.simplify(node
.branch
->cond
);
386 ctx
.simplifications
.push_back(node
.branch
);
387 ctx
.simplifications
.push_back(node
.branch
->trueLabel
);
388 Simplify::visit(*node
.block
, ctx
);
391 ast::Goto
* gt
= new ast::Goto
;
392 gt
->label
= node
.beginLabel
->name
;
393 ctx
.simplifications
.push_back(gt
);
394 ctx
.simplifications
.push_back(node
.branch
->falseLabel
);
405 static void visitDoWhile(ast::Node
& node_
, Simplify
& ctx
)
407 ast::DoWhile
& node
= reinterpret_cast<ast::DoWhile
&> (node_
);
409 assert(node
.branch
->cond
);
411 node
.branch
->trueLabel
= new ast::Label
;
412 node
.branch
->trueLabel
->name
= std::string("do_while_1_") + ctx
.nextId();
413 node
.branch
->falseLabel
= new ast::Label
;
414 node
.branch
->falseLabel
->name
= std::string("do_while_2_") + ctx
.nextId();
415 ctx
.simplifications
.push_back(node
.branch
->trueLabel
);
417 Simplify::visit(*node
.block
, ctx
);
419 ctx
.simplify(node
.branch
->cond
);
422 ctx
.simplifications
.push_back(node
.branch
);
423 ctx
.simplifications
.push_back(node
.branch
->falseLabel
);
427 Simplify::simplifyLValue(ast::Exp
*& node
)
429 if (node
->nodeType
== ast::SymbolExp::nodeTypeId())
431 if (node
->nodeType
== ast::DereferenceExp::nodeTypeId())
433 ast::DereferenceExp
* deref
= ast::ast_cast
<ast::DereferenceExp
*>(node
);
434 simplify(deref
->exp
);
436 assert(deref
->exp
->nodeType
== ast::SymbolExp::nodeTypeId());
445 #define REGISTER_METHOD(Class) \
446 registerMethod(ast::Class::nodeTypeId(), visit##Class)
448 REGISTER_METHOD(Exp
);
449 REGISTER_METHOD(VoidExp
);
450 REGISTER_METHOD(AssignExp
);
452 REGISTER_METHOD(EqExp
);
453 REGISTER_METHOD(NeqExp
);
454 REGISTER_METHOD(LtExp
);
455 REGISTER_METHOD(LtEqExp
);
456 REGISTER_METHOD(GtExp
);
457 REGISTER_METHOD(GtEqExp
);
458 REGISTER_METHOD(AddExp
);
459 REGISTER_METHOD(SubExp
);
460 REGISTER_METHOD(MulExp
);
461 REGISTER_METHOD(DivExp
);
462 REGISTER_METHOD(ModExp
);
464 REGISTER_METHOD(AndExp
);
465 REGISTER_METHOD(OrExp
);
466 REGISTER_METHOD(XorExp
);
468 REGISTER_METHOD(AndAndExp
);
469 REGISTER_METHOD(OrOrExp
);
471 REGISTER_METHOD(ShlExp
);
472 REGISTER_METHOD(AShrExp
);
473 REGISTER_METHOD(LShrExp
);
475 REGISTER_METHOD(NotExp
);
476 REGISTER_METHOD(NegExp
);
477 REGISTER_METHOD(BangExp
);
479 REGISTER_METHOD(NumberExp
);
480 REGISTER_METHOD(StringExp
);
481 REGISTER_METHOD(IdExp
);
482 REGISTER_METHOD(SymbolExp
);
483 REGISTER_METHOD(AtExp
);
484 REGISTER_METHOD(DereferenceExp
);
485 REGISTER_METHOD(DereferenceByIndexExp
);
486 REGISTER_METHOD(CallExp
);
487 REGISTER_METHOD(Block
);
489 REGISTER_METHOD(CastExp
);
491 REGISTER_METHOD(Label
);
492 REGISTER_METHOD(Goto
);
493 REGISTER_METHOD(Return
);
495 REGISTER_METHOD(While
);
496 REGISTER_METHOD(DoWhile
);
498 completeWith
<Browser
<Simplify
> >();