2 #include <boost/foreach.hpp>
4 #include <core/assert.hh>
5 #include <ast/cast-tables.hh>
6 #include <ast/clone.hh>
7 #include <ast/node-factory.hh>
8 #include <ast/type-checker-visitor.hh>
9 #include <ast/simplify-visitor.hh>
13 /// @defgroup Visitors
15 * @class SimplifyVisitor
18 * <b>Algorithm</b><br>
20 * - for every instruction
21 * - split the instruction in 3 address instruction
24 SimplifyVisitor::SimplifyVisitor()
32 SimplifyVisitor::~SimplifyVisitor()
37 SimplifyVisitor::nextId()
40 ss
<< "$" << ++nextId_
;
45 SimplifyVisitor::currentId() const
53 SimplifyVisitor::makeTmpResult(Exp
& node
)
55 if (node
.type
->nodeType
== VoidType::nodeTypeId())
58 simplifications_
.push_back(&node
);
62 AssignExp
* assign
= new AssignExp();
63 assign
->value
= &node
;
64 assign
->dest
= new Symbol();
65 assign
->dest
->name
= nextId();
66 assign
->dest
->type
= node
.type
;
67 assign
->type
= node
.type
;
68 simplifications_
.push_back(assign
);
70 IdExp
* id
= new IdExp();
71 id
->symbol
= new Symbol
;
72 id
->symbol
->name
= assign
->dest
->name
;
73 id
->symbol
->type
= node
.type
;
74 id
->symbol
->address
= new RegisterAddress
;
80 SimplifyVisitor::visit(Block
& block
)
83 std::vector
<Node
*> backup
= simplifications_
;
84 simplifications_
.clear();
86 BOOST_FOREACH (Node
* node
, (*block
.statements
))
92 *block
.statements
= simplifications_
;
93 simplifications_
= backup
;
97 SimplifyVisitor::visit(Exp
& /*node*/)
99 assert_msg(false, "unimplemented visit method");
103 SimplifyVisitor::visit(VoidExp
& node
)
105 replacement_
= &node
;
108 #define SIMPLIFY_UNARY_EXP(Type) \
111 * - Simplify childs \
112 * - Create a new id. \
113 * - Create a new assign exp to id. \
114 * - Create a IdExp and tell replace the parent's child with it. \
117 SimplifyVisitor::visit(Type & node) \
120 simplify(node.exp); \
122 makeTmpResult(node); \
125 SIMPLIFY_UNARY_EXP(NotExp
)
126 SIMPLIFY_UNARY_EXP(BangExp
)
127 SIMPLIFY_UNARY_EXP(NegExp
)
129 #define SIMPLIFY_BINARY_EXP(Type) \
132 * - Simplify childs \
133 * - Create a new id. \
134 * - Create a new assign exp to id. \
135 * - Create a IdExp and tell replace the parent's child with it. \
138 SimplifyVisitor::visit(Type & node) \
140 simplify(node.left); \
141 simplify(node.right); \
143 makeTmpResult(node); \
146 SIMPLIFY_BINARY_EXP(EqExp
)
147 SIMPLIFY_BINARY_EXP(NeqExp
)
148 SIMPLIFY_BINARY_EXP(LtExp
)
149 SIMPLIFY_BINARY_EXP(LtEqExp
)
150 SIMPLIFY_BINARY_EXP(GtExp
)
151 SIMPLIFY_BINARY_EXP(GtEqExp
)
153 SIMPLIFY_BINARY_EXP(AddExp
)
154 SIMPLIFY_BINARY_EXP(SubExp
)
155 SIMPLIFY_BINARY_EXP(MulExp
)
156 SIMPLIFY_BINARY_EXP(DivExp
)
157 SIMPLIFY_BINARY_EXP(ModExp
)
159 SIMPLIFY_BINARY_EXP(AndExp
)
160 SIMPLIFY_BINARY_EXP(OrExp
)
161 SIMPLIFY_BINARY_EXP(XorExp
)
163 SIMPLIFY_BINARY_EXP(AndAndExp
)
164 SIMPLIFY_BINARY_EXP(OrOrExp
)
166 SIMPLIFY_BINARY_EXP(ShlExp
)
167 SIMPLIFY_BINARY_EXP(AShrExp
)
168 SIMPLIFY_BINARY_EXP(LShrExp
)
171 SimplifyVisitor::visit(AssignExp
& node
)
175 assert(node
.dest
->address
);
177 simplify(node
.value
);
179 if (node
.dest
->address
->nodeType
== MemoryAddress::nodeTypeId())
181 StoreVar
* sv
= new StoreVar();
182 sv
->name
= node
.dest
->name
;
183 sv
->value
= replacement_
;
184 simplifications_
.push_back(sv
);
188 /* update the address of the variable in the symbol table */
189 MemoryAddress
* addr
= reinterpret_cast<MemoryAddress
*> (node
.dest
->address
);
190 addr
->name
= node
.dest
->name
+ "_" + nextId();
192 node
.dest
= clone(node
.dest
);
193 IdExp
* id
= new IdExp
;
194 id
->symbol
= node
.dest
;
197 simplifications_
.push_back(&node
);
201 SimplifyVisitor::visit(NumberExp
& node
)
203 replacement_
= &node
;
207 SimplifyVisitor::visit(IdExp
& node
)
209 if (node
.symbol
->address
->nodeType
== MemoryAddress::nodeTypeId())
211 IdExp
* id
= new IdExp
;
212 id
->symbol
= new Symbol
;
213 id
->symbol
->name
= node
.symbol
->name
+ "_" + nextId();;
214 id
->symbol
->type
= unreferencedType(node
.type
);
215 id
->symbol
->address
= new RegisterAddress
;
216 id
->type
= id
->symbol
->type
;
219 LoadVar
* lv
= new LoadVar
;
220 lv
->to
= id
->symbol
->name
;
222 simplifications_
.push_back(lv
);
225 replacement_
= &node
;
229 SimplifyVisitor::visit(DereferenceExp
& node
)
233 LoadVar
* lv
= new LoadVar
;
236 simplifications_
.push_back(lv
);
238 IdExp
* id
= new IdExp
;
239 id
->symbol
= new Symbol
;
240 id
->symbol
->name
= lv
->to
;
241 id
->symbol
->type
= node
.type
;
242 id
->symbol
->address
= new RegisterAddress
;
243 id
->type
= node
.type
;
249 * - compute the new address:
250 * - addrui = ptrtoui addr
251 * - offset = index * sizeof(*addr)
252 * - newaddrui = ptrtoui + offset
253 * - newaddr = cast(*, newaddrui)
257 SimplifyVisitor::visit(DereferenceByIndexExp
& node
)
260 simplify(node
.index
);
262 /* cast node.exp to uint */
263 CastExp
* cast1
= NodeFactory::createCastPtrToUInt(node
.exp
);
265 /* compute the offset */
266 MulExp
* mul
= new MulExp
;
267 mul
->left
= node
.index
;
268 mul
->right
= NodeFactory::createSizeofValue(node
.type
);
270 /* add the offset to the uint addr */
271 AddExp
* add
= new AddExp
;
275 /* cast uint addr to ptr */
276 Exp
* cast2
= NodeFactory::createCastUIntToPtr(add
, node
.exp
->type
);
278 /// @todo move this stuff to the typechecker, and just do an addition.
279 TypeCheckerVisitor v
;
284 /* the dereference step */
285 LoadVar
* lv
= new LoadVar
;
288 simplifications_
.push_back(lv
);
290 IdExp
* id
= new IdExp
;
291 id
->symbol
= new Symbol
;
292 id
->symbol
->name
= lv
->to
;
293 id
->symbol
->type
= node
.type
;
294 id
->symbol
->address
= new RegisterAddress
;
295 id
->type
= node
.type
;
300 SimplifyVisitor::visit(CallExp
& node
)
302 BOOST_FOREACH (Exp
*& exp
, (*node
.args
))
310 * develop the cast, and simplify it
313 SimplifyVisitor::visit(CastExp
& node
)
317 if (!castToBestType(node
.type
, node
.exp
->type
))
324 SimplifyVisitor::visit(Label
& node
)
326 simplifications_
.push_back(&node
);
330 SimplifyVisitor::visit(Goto
& node
)
332 simplifications_
.push_back(&node
);
336 SimplifyVisitor::visit(Return
& node
)
339 simplifications_
.push_back(&node
);
343 SimplifyVisitor::visit(If
& node
)
345 simplify(node
.branch
->cond
);
346 simplifications_
.push_back(node
.branch
);
348 node
.branch
->trueLabel
= new Label
;
349 node
.branch
->trueLabel
->name
= std::string("if_true_") + nextId();
350 node
.branch
->falseLabel
= new Label
;
351 node
.branch
->falseLabel
->name
= std::string("if_false_") + nextId();
352 node
.endLabel
= new Label
;
353 node
.endLabel
->name
= std::string("if_end_") + nextId();
355 simplifications_
.push_back(node
.branch
->trueLabel
);
356 node
.trueBlock
->accept(*this);
357 Goto
* gotoNode
= new Goto
;
358 gotoNode
->label
= node
.endLabel
->name
;
360 simplifications_
.push_back(node
.branch
->falseLabel
);
361 node
.falseBlock
->accept(*this);
362 simplifications_
.push_back(node
.endLabel
);
366 SimplifyVisitor::visit(While
& node
)
369 assert(node
.branch
->cond
);
371 node
.beginLabel
= new Label
;
372 node
.beginLabel
->name
= std::string("do_while_1_") + nextId();
373 node
.branch
->trueLabel
= new Label
;
374 node
.branch
->trueLabel
->name
= std::string("do_while_2_") + nextId();
375 node
.branch
->falseLabel
= new Label
;
376 node
.branch
->falseLabel
->name
= std::string("do_while_3_") + nextId();
378 simplifications_
.push_back(node
.beginLabel
);
379 simplify(node
.branch
->cond
);
380 simplifications_
.push_back(node
.branch
);
381 simplifications_
.push_back(node
.branch
->trueLabel
);
382 node
.block
->accept(*this);
385 Goto
* gt
= new Goto
;
386 gt
->label
= node
.beginLabel
->name
;
387 simplifications_
.push_back(gt
);
388 simplifications_
.push_back(node
.branch
->falseLabel
);
392 SimplifyVisitor::visit(DoWhile
& node
)
395 assert(node
.branch
->cond
);
397 node
.branch
->trueLabel
= new Label
;
398 node
.branch
->trueLabel
->name
= std::string("do_while_1_") + nextId();
399 node
.branch
->falseLabel
= new Label
;
400 node
.branch
->falseLabel
->name
= std::string("do_while_2_") + nextId();
401 simplifications_
.push_back(node
.branch
->trueLabel
);
403 node
.block
->accept(*this);
405 simplify(node
.branch
->cond
);
408 simplifications_
.push_back(node
.branch
);
409 simplifications_
.push_back(node
.branch
->falseLabel
);