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/clone.hh>
8 #include <ozulis/ast/node-factory.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::IdExp
* id
= new ast::IdExp();
78 id
->symbol
= new ast::Symbol
;
79 id
->symbol
->name
= nextId();
80 id
->symbol
->type
= node
.type
;
81 id
->symbol
->address
= new ast::RegisterAddress
;
84 ast::AssignExp
* assign
= new ast::AssignExp();
85 assign
->value
= &node
;
87 assign
->type
= node
.type
;
88 simplifications
.push_back(assign
);
93 static void visitBlock(ast::Node
& node_
, Simplify
& ctx
)
95 ast::Block
& block
= reinterpret_cast<ast::Block
&> (node_
);
96 ctx
.scope
= block
.scope
;
97 std::vector
<ast::Node
*> backup
= ctx
.simplifications
;
98 ctx
.simplifications
.clear();
100 BOOST_FOREACH (ast::Node
* node
, (*block
.statements
))
103 Simplify::visit(*node
, ctx
);
106 *block
.statements
= ctx
.simplifications
;
107 ctx
.simplifications
= backup
;
110 static void visitExp(ast::Node
& /*node_*/, Simplify
& /*ctx*/)
112 assert_msg(false, "unimplemented visit method");
115 static void visitVoidExp(ast::Node
& node_
, Simplify
& ctx
)
117 ast::VoidExp
& node
= reinterpret_cast<ast::VoidExp
&> (node_
);
118 ctx
.replacement
= &node
;
121 #define SIMPLIFY_UNARY_EXP(Type) \
124 * - Simplify childs \
125 * - Create a new id. \
126 * - Create a new assign exp to id. \
127 * - Create a IdExp and tell replace the parent's child with it. \
129 static void visit##Type(ast::Node & node_, Simplify & ctx) \
131 ast::Type & node = reinterpret_cast<ast::Type &> (node_); \
133 ctx.simplify(node.exp); \
135 ctx.makeTmpResult(node); \
138 SIMPLIFY_UNARY_EXP(NotExp
)
139 SIMPLIFY_UNARY_EXP(BangExp
)
140 SIMPLIFY_UNARY_EXP(NegExp
)
142 #define SIMPLIFY_BINARY_EXP(Type) \
145 * - Simplify childs \
146 * - Create a new id. \
147 * - Create a new assign exp to id. \
148 * - Create a IdExp and tell replace the parent's child with it. \
150 static void visit##Type(ast::Node & node_, Simplify & ctx) \
152 ast::Type & node = reinterpret_cast<ast::Type &> (node_); \
153 ctx.simplify(node.left); \
154 ctx.simplify(node.right); \
156 ctx.makeTmpResult(node); \
159 SIMPLIFY_BINARY_EXP(EqExp
)
160 SIMPLIFY_BINARY_EXP(NeqExp
)
161 SIMPLIFY_BINARY_EXP(LtExp
)
162 SIMPLIFY_BINARY_EXP(LtEqExp
)
163 SIMPLIFY_BINARY_EXP(GtExp
)
164 SIMPLIFY_BINARY_EXP(GtEqExp
)
166 SIMPLIFY_BINARY_EXP(AddExp
)
167 SIMPLIFY_BINARY_EXP(SubExp
)
168 SIMPLIFY_BINARY_EXP(MulExp
)
169 SIMPLIFY_BINARY_EXP(DivExp
)
170 SIMPLIFY_BINARY_EXP(ModExp
)
172 SIMPLIFY_BINARY_EXP(AndExp
)
173 SIMPLIFY_BINARY_EXP(OrExp
)
174 SIMPLIFY_BINARY_EXP(XorExp
)
176 SIMPLIFY_BINARY_EXP(AndAndExp
)
177 SIMPLIFY_BINARY_EXP(OrOrExp
)
179 SIMPLIFY_BINARY_EXP(ShlExp
)
180 SIMPLIFY_BINARY_EXP(AShrExp
)
181 SIMPLIFY_BINARY_EXP(LShrExp
)
184 static void visitAssignExp(ast::Node
& node_
, Simplify
& ctx
)
186 ast::AssignExp
& node
= reinterpret_cast<ast::AssignExp
&> (node_
);
191 ctx
.simplifyLValue(node
.dest
);
192 ctx
.simplify(node
.value
);
194 ast::IdExp
* dest
= ast::ast_cast
<ast::IdExp
*> (node
.dest
);
195 ast::StoreVar
* sv
= new ast::StoreVar();
196 sv
->name
= dest
->symbol
->name
;
197 sv
->value
= ctx
.replacement
; // node.value
198 ctx
.simplifications
.push_back(sv
);
202 static void visitNumberExp(ast::Node
& node_
, Simplify
& ctx
)
204 ast::NumberExp
& node
= reinterpret_cast<ast::NumberExp
&> (node_
);
205 ctx
.replacement
= &node
;
208 static void visitIdExp(ast::Node
& node_
, Simplify
& ctx
)
210 ast::IdExp
& node
= reinterpret_cast<ast::IdExp
&> (node_
);
211 if (node
.symbol
->address
->nodeType
== ast::MemoryAddress::nodeTypeId())
213 ast::IdExp
* id
= new ast::IdExp
;
214 id
->symbol
= new ast::Symbol
;
215 id
->symbol
->name
= node
.symbol
->name
+ "_" + ctx
.nextId();;
216 id
->symbol
->type
= unreferencedType(node
.type
);
217 id
->symbol
->address
= new ast::RegisterAddress
;
218 id
->type
= id
->symbol
->type
;
219 ctx
.replacement
= id
;
221 ast::LoadVar
* lv
= new ast::LoadVar
;
222 lv
->to
= id
->symbol
->name
;
224 ctx
.simplifications
.push_back(lv
);
227 ctx
.replacement
= &node
;
230 static void visitAtExp(ast::Node
& node_
, Simplify
& ctx
)
232 ast::AtExp
& node
= reinterpret_cast<ast::AtExp
&> (node_
);
233 ctx
.replacement
= &node
;
234 ctx
.simplifyLValue(ctx
.replacement
);
237 static void visitDereferenceExp(ast::Node
& node_
, Simplify
& ctx
)
239 ast::DereferenceExp
& node
= reinterpret_cast<ast::DereferenceExp
&> (node_
);
240 ctx
.simplify(node
.exp
);
242 ast::LoadVar
* lv
= new ast::LoadVar
;
243 lv
->to
= ctx
.nextId();
245 ctx
.simplifications
.push_back(lv
);
247 ast::IdExp
* id
= new ast::IdExp
;
248 id
->symbol
= new ast::Symbol
;
249 id
->symbol
->name
= lv
->to
;
250 id
->symbol
->type
= node
.type
;
251 id
->symbol
->address
= new ast::RegisterAddress
;
252 id
->type
= node
.type
;
253 ctx
.replacement
= id
;
257 * @internal just do (node.exp + node.index)*
259 static void visitDereferenceByIndexExp(ast::Node
& node_
, Simplify
& ctx
)
261 ast::DereferenceByIndexExp
& node
= reinterpret_cast<ast::DereferenceByIndexExp
&> (node_
);
262 ast::AddExp
* add
= new ast::AddExp
;
263 add
->left
= node
.exp
;
264 add
->right
= node
.index
;
266 ast::DereferenceExp
* deref
= new ast::DereferenceExp
;
268 ast::Exp
* tmp
= deref
;
271 v
.setScope(ctx
.scope
);
274 ctx
.replacement
= tmp
;
277 static void visitCallExp(ast::Node
& node_
, Simplify
& ctx
)
279 ast::CallExp
& node
= reinterpret_cast<ast::CallExp
&> (node_
);
280 BOOST_FOREACH (ast::Exp
*& exp
, (*node
.args
))
283 ctx
.makeTmpResult(node
);
288 * develop the cast, and simplify it
290 static void visitCastExp(ast::Node
& node_
, Simplify
& ctx
)
292 ast::CastExp
& node
= reinterpret_cast<ast::CastExp
&> (node_
);
293 ctx
.simplify(node
.exp
);
295 if (!castToBestType(node
.type
, node
.exp
->type
))
298 ctx
.makeTmpResult(node
);
301 static void visitLabel(ast::Node
& node_
, Simplify
& ctx
)
303 ast::Label
& node
= reinterpret_cast<ast::Label
&> (node_
);
304 ctx
.simplifications
.push_back(&node
);
307 static void visitGoto(ast::Node
& node_
, Simplify
& ctx
)
309 ast::Goto
& node
= reinterpret_cast<ast::Goto
&> (node_
);
310 ctx
.simplifications
.push_back(&node
);
313 static void visitReturn(ast::Node
& node_
, Simplify
& ctx
)
315 ast::Return
& node
= reinterpret_cast<ast::Return
&> (node_
);
316 ctx
.simplify(node
.exp
);
317 ctx
.simplifications
.push_back(&node
);
320 static void visitIf(ast::Node
& node_
, Simplify
& ctx
)
322 ast::If
& node
= reinterpret_cast<ast::If
&> (node_
);
323 ctx
.simplify(node
.branch
->cond
);
324 ctx
.simplifications
.push_back(node
.branch
);
326 node
.branch
->trueLabel
= new ast::Label
;
327 node
.branch
->trueLabel
->name
= std::string("if_true_") + ctx
.nextId();
328 node
.branch
->falseLabel
= new ast::Label
;
329 node
.branch
->falseLabel
->name
= std::string("if_false_") + ctx
.nextId();
330 node
.endLabel
= new ast::Label
;
331 node
.endLabel
->name
= std::string("if_end_") + ctx
.nextId();
333 ctx
.simplifications
.push_back(node
.branch
->trueLabel
);
334 Simplify::visit(*node
.trueBlock
, ctx
);
335 ast::Goto
* gotoNode
= new ast::Goto
;
336 gotoNode
->label
= node
.endLabel
->name
;
338 ctx
.simplifications
.push_back(node
.branch
->falseLabel
);
339 Simplify::visit(*node
.falseBlock
, ctx
);
340 ctx
.simplifications
.push_back(node
.endLabel
);
343 static void visitWhile(ast::Node
& node_
, Simplify
& ctx
)
345 ast::While
& node
= reinterpret_cast<ast::While
&> (node_
);
347 assert(node
.branch
->cond
);
349 node
.beginLabel
= new ast::Label
;
350 node
.beginLabel
->name
= std::string("do_while_1_") + ctx
.nextId();
351 node
.branch
->trueLabel
= new ast::Label
;
352 node
.branch
->trueLabel
->name
= std::string("do_while_2_") + ctx
.nextId();
353 node
.branch
->falseLabel
= new ast::Label
;
354 node
.branch
->falseLabel
->name
= std::string("do_while_3_") + ctx
.nextId();
356 ctx
.simplifications
.push_back(node
.beginLabel
);
357 ctx
.simplify(node
.branch
->cond
);
358 ctx
.simplifications
.push_back(node
.branch
);
359 ctx
.simplifications
.push_back(node
.branch
->trueLabel
);
360 Simplify::visit(*node
.block
, ctx
);
363 ast::Goto
* gt
= new ast::Goto
;
364 gt
->label
= node
.beginLabel
->name
;
365 ctx
.simplifications
.push_back(gt
);
366 ctx
.simplifications
.push_back(node
.branch
->falseLabel
);
369 static void visitDoWhile(ast::Node
& node_
, Simplify
& ctx
)
371 ast::DoWhile
& node
= reinterpret_cast<ast::DoWhile
&> (node_
);
373 assert(node
.branch
->cond
);
375 node
.branch
->trueLabel
= new ast::Label
;
376 node
.branch
->trueLabel
->name
= std::string("do_while_1_") + ctx
.nextId();
377 node
.branch
->falseLabel
= new ast::Label
;
378 node
.branch
->falseLabel
->name
= std::string("do_while_2_") + ctx
.nextId();
379 ctx
.simplifications
.push_back(node
.branch
->trueLabel
);
381 Simplify::visit(*node
.block
, ctx
);
383 ctx
.simplify(node
.branch
->cond
);
386 ctx
.simplifications
.push_back(node
.branch
);
387 ctx
.simplifications
.push_back(node
.branch
->falseLabel
);
391 Simplify::simplifyLValue(ast::Exp
*& node
)
393 if (node
->nodeType
== ast::IdExp::nodeTypeId())
395 if (node
->nodeType
== ast::DereferenceExp::nodeTypeId())
397 ast::DereferenceExp
* deref
= ast::ast_cast
<ast::DereferenceExp
*>(node
);
398 simplify(deref
->exp
);
400 assert(deref
->exp
->nodeType
== ast::IdExp::nodeTypeId());
409 #define REGISTER_METHOD(Class) \
410 registerMethod(ast::Class::nodeTypeId(), visit##Class)
412 REGISTER_METHOD(Exp
);
413 REGISTER_METHOD(VoidExp
);
414 REGISTER_METHOD(AssignExp
);
416 REGISTER_METHOD(EqExp
);
417 REGISTER_METHOD(NeqExp
);
418 REGISTER_METHOD(LtExp
);
419 REGISTER_METHOD(LtEqExp
);
420 REGISTER_METHOD(GtExp
);
421 REGISTER_METHOD(GtEqExp
);
422 REGISTER_METHOD(AddExp
);
423 REGISTER_METHOD(SubExp
);
424 REGISTER_METHOD(MulExp
);
425 REGISTER_METHOD(DivExp
);
426 REGISTER_METHOD(ModExp
);
428 REGISTER_METHOD(AndExp
);
429 REGISTER_METHOD(OrExp
);
430 REGISTER_METHOD(XorExp
);
432 REGISTER_METHOD(AndAndExp
);
433 REGISTER_METHOD(OrOrExp
);
435 REGISTER_METHOD(ShlExp
);
436 REGISTER_METHOD(AShrExp
);
437 REGISTER_METHOD(LShrExp
);
439 REGISTER_METHOD(NotExp
);
440 REGISTER_METHOD(NegExp
);
441 REGISTER_METHOD(BangExp
);
443 REGISTER_METHOD(NumberExp
);
444 REGISTER_METHOD(IdExp
);
445 REGISTER_METHOD(AtExp
);
446 REGISTER_METHOD(DereferenceExp
);
447 REGISTER_METHOD(DereferenceByIndexExp
);
448 REGISTER_METHOD(CallExp
);
449 REGISTER_METHOD(Block
);
451 REGISTER_METHOD(CastExp
);
453 REGISTER_METHOD(Label
);
454 REGISTER_METHOD(Goto
);
455 REGISTER_METHOD(Return
);
457 REGISTER_METHOD(While
);
458 REGISTER_METHOD(DoWhile
);
460 completeWith
<Browser
<Simplify
> >();