24 #ifndef OTAWA_DFA_HAI_HALFABSINT_H
25 #define OTAWA_DFA_HAI_HALFABSINT_H
28 #include <elm/assert.h>
29 #include <elm/genstruct/VectorQueue.h>
30 #include <elm/genstruct/Vector.h>
41 #if defined(NDEBUG) || !defined(HAI_DEBUG)
44 # define HAI_TRACE(x) cerr << x << io::endl
47 namespace otawa {
namespace dfa {
namespace hai {
63 template <
class FixPo
int>
74 typename FixPoint::Domain
in,
out;
92 typename FixPoint::Domain *entdom = 0,
BasicBlock *start_bb = 0);
99 template <
class FixPo
int>
102 template <
class FixPo
int>
123 template <
class FixPo
int>
129 cfgs.
add(&entry_cfg);
130 for(
int i = 0; i < cfgs.
count(); i++)
133 this->fp.unmarkEdge(*
out);
135 cfgs.
add(
out->calledCFG());
141 template <
class FixPo
int>
143 return(FIXPOINT_STATE(bb));
148 template <
class FixPo
int>
150 fp.assign(
in, fp.bottom());
154 fp.assign(
in, entdom);
159 else if (current->isEntry()) {
160 fp.assign(
in, *fp.getMark(current));
161 fp.unmarkEdge(current);
165 else if (!next_edge && !call_edges.isEmpty()) {
169 fp.lub(
in, *fp.getMark(*iter));
170 fp.unmarkEdge(*iter);
183 FIXPOINT_STATE(current) = fp.newState();
184 fp.fixPoint(current, fixpoint,
in,
FIRST_ITER(current));
185 HAI_TRACE(
"\t\tat loop header " << current <<
", fixpoint reached = " << fixpoint);
190 FIXED(current) = fixpoint;
201 fp.unmarkEdge(*inedge);
208 fp.fixPointReached(current);
209 delete FIXPOINT_STATE(current);
210 FIXPOINT_STATE(current) = 0;
221 fp.unmarkEdge(*inedge);
225 fp.unmarkEdge(current);
238 typename FixPoint::Domain *edgeState = fp.getMark(*inedge);
242 fp.updateEdge(*inedge, *edgeState);
243 fp.lub(
in, *edgeState);
245 fp.unmarkEdge(*inedge);
250 typename FixPoint::Domain *bypassState = fp.getMark(current);
252 fp.lub(
in, *bypassState);
253 fp.unmarkEdge(current);
262 template <
class FixPo
int>
269 cerr <<
"WARNING: infinite loop found at " << current << io::endl;
272 HAI_TRACE(
"\t\tpushing edge " << iter->source() <<
" -> " << iter->target());
273 if(!alreadyAdded.
contains(iter->target()) && tryAddToWorkList(iter->target()))
274 alreadyAdded.
add(iter->target());
275 fp.leaveContext(*fp.getMark(*iter), current,
CTX_LOOP);
280 else if (current->isExit() && (callStack->length() > 0)) {
283 HAI_TRACE(
"\t\tupdating exit block while returning from call at " << current);
284 fp.update(
out,
in, current);
288 cur_cfg = cfgStack->pop();
289 HAI_TRACE(
"\t\treturning to CFG " << cur_cfg->label());
293 fp.markEdge(edge,
out);
294 workList->push(edge->
source());
298 else if (next_edge) {
301 HAI_TRACE(
"\t\tupdating for BB " << current <<
" while visiting call-node for the first time");
302 fp.update(
out,
in, current);
305 BasicBlock *func_entry = iter->calledCFG()->entry();
306 fp.markEdge(func_entry,
out);
311 callStack->push(next_edge);
312 cfgStack->push(cur_cfg);
315 cur_cfg = next_edge->calledCFG();
316 HAI_TRACE(
"\tcalling CFG " << cur_cfg->label());
317 workList->push(cur_cfg->entry());
322 else if (!call_edges.isEmpty()) {
323 HAI_TRACE(
"\t\treturning from function calls at " << current);
331 fp.update(
out,
in, current);
332 fp.blockInterpreted(current,
in,
out, cur_cfg, callStack);
337 template <
class FixPo
int>
349 fp.markEdge(*outedge,
out);
353 tryAddToWorkList(outedge->target());
366 template <
class FixPo
int>
373 call_edges.
add(*outedge);
374 if (fp.getMark(*outedge)) {
376 }
else if (!next_edge)
377 next_edge = *outedge;
384 template <
class FixPo
int>
387 typename FixPoint::Domain default_entry(fp.entry());
394 main_cfg = &entry_cfg;
396 start_bb = main_cfg->
entry();
398 entdom = &default_entry;
405 workList->push(start_bb);
408 while (!workList->isEmpty()) {
411 current = workList->pop();
412 next_edge = detectCalls(enter_call, call_edges, current);
415 inputProcessing(*entdom);
424 template <
class FixPo
int>
426 typename FixPoint::Domain result(fp.bottom());
437 typename FixPoint::Domain *edgeState = fp.getMark(*inedge);
439 HAI_TRACE(
"\t\t\twith " << *inedge <<
" = " << *edgeState);
440 fp.lub(result, *edgeState);
450 template <
class FixPo
int>
452 typename FixPoint::Domain result(fp.bottom());
461 typename FixPoint::Domain *edgeState = fp.getMark(*inedge);
463 HAI_TRACE(
"\t\t\twith " << *inedge <<
" = " << *edgeState);
464 fp.lub(result, *edgeState);
469 typename FixPoint::Domain *bypassState = fp.getMark(bb);
471 fp.lub(result, *bypassState);
473 fp.enterContext(result, bb,
CTX_LOOP);
479 template <
class FixPo
int>
487 if (!isEdgeDone(*inedge)) {
493 typename FixPoint::Domain *bypassState = fp.getMark(bb);
502 cerr <<
"Ignoring back-edges for loop header " << bb->
number() <<
" because it's the first iteration.\n";
505 HAI_TRACE(
"\t\tadding " << bb <<
" to worklist");
512 template <
class FixPo
int>
533 #endif // OTAWA_DFA_HAI_HALFABSINT_H
Identifier< bool > FIXED
This property is attached to the loop headers, and is true if the FixPoint for the associated loop ha...
bool tryAddToWorkList(BasicBlock *bb)
Try to add the BasicBlock to the worklist.
Definition: HalfAbsInt.h:480
FixPoint::Domain backEdgeUnion(BasicBlock *bb)
Given a loop header, returns the union of the value of its back edges.
Definition: HalfAbsInt.h:425
dtd::Element edge(dtd::make("edge", _EDGE).attr(source).attr(target).attr(called))
HalfAbsInt(FixPoint &_fp, WorkSpace &_fw)
Definition: HalfAbsInt.h:103
Edges of this kind are only found in a virtual CFG.
Definition: Edge.h:43
bool mainEntry
Definition: HalfAbsInt.h:79
elm::genstruct::Vector< CFG * > * cfgStack
Definition: HalfAbsInt.h:72
BasicBlock * source(void) const
Definition: Edge.h:52
Edge * detectCalls(bool &enter_call, elm::genstruct::Vector< Edge * > &call_edges, BasicBlock *bb)
Definition: HalfAbsInt.h:367
bool fixpoint
Definition: HalfAbsInt.h:78
BasicBlock * current
Definition: HalfAbsInt.h:73
Identifier< BasicBlock * > LOOP_EXIT_EDGE
Is defined for an Edge if this Edge is the exit-edge of any loop.
Kind of an edge matching a sub-program call.
Definition: Edge.h:40
Identifier< elm::genstruct::Vector< Edge * > * > EXIT_LIST
Defined for any BasicBlock that is a loop header.
Identifier< bool > HAI_DONT_ENTER
This property, when set to TRUE on a BasicBlock or a CFG, prevents HalfAbsInt from following edges to...
elm::genstruct::Vector< Edge * > * callStack
Definition: HalfAbsInt.h:71
Identifier< bool > LOOP_HEADER
Identifier for marking basic blocks that are entries of loops.
BasicBlock * entry(void)
Get the entry basic block of the CFG.
Definition: CFG.h:63
FixPoint::Domain entryEdgeUnion(BasicBlock *bb)
Given a loop header, returns the union of the value of is entry edges (the entry edges are the in-edg...
Definition: HalfAbsInt.h:451
Edge * next_edge
Definition: HalfAbsInt.h:76
dtd::Element bb(dtd::make("bb", _BB).attr(id).attr(address).attr(size))
Control Flow Graph representation.
Definition: CFG.h:42
Identifier< BasicBlock * > HAI_BYPASS_TARGET
Identifier< CFG * > ENTRY_CFG
This property may be used to pass the entry CFG to a CFG processor or is used by the CFG processor to...
Definition: CFGProcessor.h:64
FixPoint::Domain in
Definition: HalfAbsInt.h:74
void outputProcessing()
Definition: HalfAbsInt.h:263
Implements abstract interpretation.
Definition: HalfAbsInt.h:64
bool enter_call
Definition: HalfAbsInt.h:77
static Identifier< typename FixPoint::FixPointState * > FIXPOINT_STATE
Definition: HalfAbsInt.h:81
A workspace represents a program, its run-time and all information about WCET computation or any othe...
Definition: WorkSpace.h:67
static bool dominates(BasicBlock *bb1, BasicBlock *bb2)
Test if the first basic block dominates the second one.
Definition: util_Dominance.cpp:164
~HalfAbsInt(void)
Definition: HalfAbsInt.h:124
Definition: BasicBlock.h:165
int number(void) const
Get the number hooked on this basic block, that is, value of ID_Index property.
Definition: BasicBlock.h:146
Identifier< bool > FIRST_ITER
This property is attached for the loop header, and is true if the first iteration of the associated l...
FixPoint & fp
Definition: HalfAbsInt.h:66
sys::SystemOutStream & out
elm::genstruct::Vector< BasicBlock * > * workList
Definition: HalfAbsInt.h:70
hai_context_t
Definition: HalfAbsInt.h:50
Definition: BasicBlock.h:160
CFG * cur_cfg
Definition: HalfAbsInt.h:69
inst add(int d, int a, int b)
Definition: inst.h:163
This class represents edges in the CFG representation.
Definition: Edge.h:33
Definition: HalfAbsInt.h:51
CFG & entry_cfg
Definition: HalfAbsInt.h:68
BasicBlock * target(void) const
Definition: Edge.h:53
#define HAI_TRACE(x)
Definition: HalfAbsInt.h:42
FixPoint::Domain out
Definition: HalfAbsInt.h:74
int solve(otawa::CFG *main_cfg=0, typename FixPoint::Domain *entdom=0, BasicBlock *start_bb=0)
Do the abstract interpretation of the CFG.
Definition: HalfAbsInt.h:385
This is the minimal definition of a basic block.
Definition: BasicBlock.h:43
void inputProcessing(typename FixPoint::Domain &entdom)
Definition: HalfAbsInt.h:149
WorkSpace & fw
Definition: HalfAbsInt.h:67
bool contains(const T &value) const
FixPoint::FixPointState * getFixPointState(BasicBlock *bb)
Get the FixPointState of a loop.
Definition: HalfAbsInt.h:142
Identifier< BasicBlock * > HAI_BYPASS_SOURCE
This property enables the user to create a virtual "bypass" edge from the source block to the target ...
void addSuccessors()
Definition: HalfAbsInt.h:338
Definition: HalfAbsInt.h:52
bool isEdgeDone(Edge *edge)
Tests if an edge verify the conditions needed to add its target BasicBlock.
Definition: HalfAbsInt.h:513
elm::genstruct::Vector< Edge * > call_edges
Definition: HalfAbsInt.h:75
Edges of this kind are only found in a virtual CFG.
Definition: Edge.h:42