memoryBlock Class Reference#include <memoryblock.h>
Inheritance diagram for memoryBlock:
List of all members.
|
Public Types |
typedef map< Location *, DestructiveKind > | destructive_assignment_map |
typedef destructive_assignment_map::iterator | destructive_assignment_map_p |
typedef destructive_assignment_map::const_iterator | destructive_assignment_map_cp |
typedef map< Location *, memoryblock_set > | complicit_assignment_map |
typedef complicit_assignment_map::iterator | complicit_assignment_map_p |
typedef complicit_assignment_map::const_iterator | complicit_assignment_map_cp |
enum | DestructiveKind { Control_flow,
Parameter_pass,
Weak_update,
Additive
} |
enum | Output_mode { NAME_ONLY,
CURRENT_VALUE,
AFTER_ASSIGNMENT,
ALL_VALUES
} |
Public Member Functions |
void | clear () |
| Clear.
|
declNode * | decl () const |
procNode * | local_to () const |
bool | is_synthetic_decl () const |
bool | write_protected () const |
void | set_write_protected () |
bool | is_indexed () const |
void | set_indexed () |
stmtLocation * | allocation_site () const |
bool | is_heap_object () const |
void | set_heap_object (stmtLocation *alloc_site) |
bool | is_allocation_object () const |
memoryUse * | current_use () const |
memoryDef * | current_def () const |
void | reset_current_def_use (Location *unused) |
void | set_current_def_use (Location *where) |
memoryBlock * | container () const |
bool | is_flow_sensitive () const |
void | set_flow_sensitive () |
void | set_flow_insensitive () |
bool | is_unify () const |
void | set_unify (bool flag) |
UnifyType * | unifyType () const |
void | unifyType (UnifyType *t) |
bool | is_single_assignment () const |
bool | is_return_value () const |
bool | set_return_value () |
procedureinfo_set & | input_to () |
memoryDef * | def_at (Location *where, bool &is_new) |
| Create a definition.
|
memoryDef * | nearest_def_at (Location *where) |
| Find the nearest dominating def.
|
memoryUse * | use_at (Location *where) |
| Find the nearest interprocedural dominating defCreate a use.
|
memoryDef * | last_def_at (basicblockLocation *block) |
| Find the last def in a basic block.
|
memoryDef * | find_def_at (Location *where) |
| Find a def.
|
memoryUse * | find_use_at (Location *where) |
| Find a use.
|
void | find_uses_at (Location *where, memoryuse_set &uses) |
| Find uses.
|
const memorydef_list & | defs () const |
| List of defs.
|
void | add_parameter_assignment (procNode *proc, stmtLocation *callsite, memoryBlock *block) |
| Add a parameter-assignment.
|
void | add_parameter_assignment (procNode *proc, stmtLocation *callsite, memoryblock_set &blocks) |
| Add a parameter-assignment.
|
const callsite_objects_map & | parameter_assignments (procNode *proc) |
| Get parameter-assignments.
|
void | apply_weak_update (Location *current, memoryDef *previous_def, memoryuse_set &uses) |
| Apply weak update.
|
void | setup_merge_uses_at (basicblockLocation *merge_location, memoryDef *reaching_def, basicblock_set &predecessors) |
| Set up a merge point.
|
void | merge_uses_at (basicblockLocation *where, memoryuse_list &uses, cfg_edge_set &active_edges, memoryDef *dominating_def, bool computePointers) |
| Process a merge point.
|
void | reachable_blocks (Location *where, bool has_use_here, memoryblock_list &worklist, memoryblock_set &already_seen, memoryBlock *null, bool components_only=false) |
| Reachable blocks.
|
memoryBlock * | get_allocation_object (memoryModel &Memory) |
| Get the allocation object.
|
memoryBlock * | allocation_object () |
| Return the allocation object.
|
Multiplicity | at_allocation (Location *current, memoryDef *reaching_def, memoryblock_set &defs, memoryuse_set &uses, memoryblock_set &changes) |
| At an allocation.
|
Multiplicity | at_deallocation (Location *current, memoryDef *reaching_def, memoryblock_set &defs, memoryuse_set &uses, memoryblock_set &changes) |
| At a deallocation.
|
memoryBlock * | top_most_container () |
| Top-most container.
|
memoryblock_set | containers () const |
memoryblock_set | top_most_containers () |
void | def_uses (memoryDef *def, memoryuse_list &uses) |
| Def uses.
|
void | prune_defs_uses () |
void | dot (const string &field_name, declNode *field_decl, memoryModel &Memory, memoryblock_set &results) |
bool | is_array () const |
bool | is_array_element () const |
void | set_array_element (memoryBlock *element) |
memoryBlock * | get_array_element () |
memoryDef * | setup_array_def () |
bool | in_scope (basicblockLocation *where) const |
void | print (ostream &o, Location *path, Output_mode mode=CURRENT_VALUE) const |
string | name () const |
string | generate_su_field_name (const string &field) const |
void | print_def_use (ostream &o) const |
void | update_def_use_chains () |
void | stats (ostream &out, bool header, long int &global_defs, long int &global_merge_defs, long int &global_weak_defs, long int &global_uses, long int &global_merge_uses) |
|
void | add_destructive_assignment (Location *where, DestructiveKind cause) |
| Add destructive assignment.
|
void | add_complicit_assignment (Location *where, memoryblock_set &objects) |
| Add complicit assignment.
|
void | add_complicit_assignment (Location *where, memoryBlock *object) |
| Add complicit assignment.
|
const destructive_assignment_map & | destructive_assignments () const |
| Get destructive assignment list.
|
const complicit_assignment_map & | complicit_assignments () const |
| Get the complicit assignment list.
|
void | add_to_flow_sensitive_list (flow_sensitive_set &flow_sensitive_objects) |
| Add to flow-sensitivity list.
|
bool | is_in_flow_sensitive_list (flow_sensitive_set &flow_sensitive_objects) |
| Find in flow-sensitivity list.
|
void | set_flow_sensitivity (flow_sensitive_set &flow_sensitive_objects) |
| Set flow sensivity.
|
void | add_to_non_unify_list (UnifyTypes &non_unify_types) |
| Add to non-unify list.
|
void | set_unification (UnifyTypes &unify_types) |
| Set unification.
|
Static Public Member Functions |
static void | stats () |
static void | print_multiplicity (Multiplicity m, ostream &out) |
| Print multiplicity values.
|
Public Attributes |
enumPropertyAnn * | property |
| Property handle.
|
memoryblock_vector | property_blocks |
| Property blocks.
|
Static Public Attributes |
static int | memoryblock_count |
Private Member Functions |
| memoryBlock (declNode *decl, bool synthetic, memoryBlock *container, procNode *local_to) |
| Create a new memoryBlock.
|
| ~memoryBlock () |
| Destructor.
|
memoryblock_set | top_most_containers (memoryblock_set &visited) |
Private Attributes |
REF memoryBlock * | _container |
| The containing struct, if there is one.
|
TREE orderedDefs | Defs |
| The uses and defs of this block.
|
TREE orderedUses | Uses |
parameter_assign_map | _parameter_assignments |
| Parameter-assignments.
|
REF memoryUse * | _current_use |
| Current use.
|
REF memoryDef * | _current_def |
| Current def.
|
component_map | _components |
| A list of things contained in this memory block.
|
declNode * | _decl |
| The declaration of this object.
|
int | _synthetic_decl:1 |
| Synthetic declaration flag.
|
int | _write_protected:1 |
| Write protected.
|
int | _is_array:1 |
| Is array.
|
int | _is_array_element:1 |
| Is array element.
|
int | _is_indexed:1 |
| Is indexed.
|
int | _is_allocation_object:1 |
| Is alloc object.
|
int | _flow_sensitive:1 |
| Flow sensitivity.
|
int | _unify:1 |
| Unification.
|
int | _single_assignment:1 |
| Single assignment.
|
int | _is_return_value:1 |
| Is return value?
|
procNode * | _local_to |
| Owner procedure.
|
stmtLocation * | _allocation_site |
| NameHeap allocation site.
|
memoryBlock * | _allocation_object |
| Initializer defAllocation object.
|
procedureinfo_set | _input_to |
| Only defOnly useInput to.
|
destructive_assignment_map | _destructive_assignments |
| Destructive assignments.
|
complicit_assignment_map | _complicit_assignments |
| Complicit assignments.
|
UnifyType * | _unifytype |
| information on unified type, if this object is unified.
|
Static Private Attributes |
static FieldNameDB | FieldNames |
Friends |
class | memoryModel |
ostream & | operator<< (ostream &o, const memoryBlock &mb) |
Classes |
class | FieldNameDB |
Member Typedef Documentation
Member Enumeration Documentation
|
- Enumeration values:
-
Control_flow |
|
Parameter_pass |
|
Weak_update |
|
Additive |
|
Definition at line 84 of file memoryblock.h. |
|
- Enumeration values:
-
NAME_ONLY |
|
CURRENT_VALUE |
|
AFTER_ASSIGNMENT |
|
ALL_VALUES |
|
Definition at line 733 of file memoryblock.h. |
Constructor & Destructor Documentation
|
Create a new memoryBlock.
The new memoryBlock is associated with the given declNode, which may have been synthetically created. Only the memoryModel class should be allocating new memoryBlocks. |
memoryBlock::~memoryBlock |
( |
|
) |
[private] |
|
|
Destructor.
Destroy the memoryBlock and all use/def information. This should only be called by the memoryModel class destructor. |
Member Function Documentation
|
Add complicit assignment.
Add one object to the complicit assignment set for the given location. |
|
Add complicit assignment.
Add the given objects to the complicit assignment set for the given location. |
|
Add destructive assignment.
Add the given cause and location to the destructive assignment list. If it already exists, the cause is overwritten. |
|
Add a parameter-assignment.
This version is used for regular formal parameter assignments, where there could be multiple actual parameters coming from different objects. |
|
Add a parameter-assignment.
Record the procedure, callsite and reaching def. This version is used for self-assignments when there is just one reaching def and it belongs to this object. |
void memoryBlock::add_to_flow_sensitive_list |
( |
flow_sensitive_set & |
flow_sensitive_objects |
) |
|
|
|
Add to flow-sensitivity list.
This method adds the block to the given flow-sensitivity list. It does this by adding a flow_sensitive_pair object containing a statement and a declaration, which can be used to identify the block on subsequent analysis passes. We need this capability because the memoryBlocks themselves are destroyed and recreated on each pass. |
void memoryBlock::add_to_non_unify_list |
( |
UnifyTypes & |
non_unify_types |
) |
|
|
|
Add to non-unify list.
This method adds the block to the given flow-sensitivity list. It does this by adding a flow_sensitive_pair object containing a statement and a declaration, which can be used to identify the block on subsequent analysis passes. We need this capability because the memoryBlocks themselves are destroyed and recreated on each pass. |
|
Return the allocation object.
Returns null if the block has no allocation object. |
stmtLocation* memoryBlock::allocation_site |
( |
|
) |
const [inline] |
|
|
Apply weak update.
This method is used to collect the previous points-to values in the case of a weak def. It assumes that a def has just been created for the given location. |
|
At an allocation.
This method handles the multiplicity analysis for a heap allocation site. It should only be called on the special allocation object. The method returns the new multiplicity value. |
|
At a deallocation.
This method handles the multiplicity analysis for a heap deallocation site. The same conditions hold for this method as for at_allocation() above. |
void memoryBlock::clear |
( |
|
) |
|
|
|
Clear.
Remove all def and use information, preparing for reanalysis. |
memoryDef* memoryBlock::current_def |
( |
|
) |
const [inline] |
|
memoryUse* memoryBlock::current_use |
( |
|
) |
const [inline] |
|
declNode* memoryBlock::decl |
( |
|
) |
const [inline] |
|
|
Create a definition.
Create a def of the memoryBlock at the given location, if one doesn't already exist. Return the memoryDef object, and also set the current_def to this def. |
|
Def uses.
Collect all the uses reached by the given definition. |
|
Find a def.
See if there is a def at the given location, but return NULL if there isn't one. |
|
Find a use.
See if there is a use of this block at the given location, returning NULL if there isn't. This version does not work for merge uses. |
|
Find uses.
Return any uses at this location. This version does work for merge uses. |
string memoryBlock::generate_su_field_name |
( |
const string & |
field |
) |
const |
|
|
Get the allocation object.
Get the allocation object, creating it if necessary. This object is used to track the state of heap allocated objects (multiplicity analysis). |
bool memoryBlock::is_allocation_object |
( |
|
) |
const [inline] |
|
bool memoryBlock::is_array |
( |
|
) |
const [inline] |
|
bool memoryBlock::is_array_element |
( |
|
) |
const [inline] |
|
bool memoryBlock::is_flow_sensitive |
( |
|
) |
const [inline] |
|
bool memoryBlock::is_heap_object |
( |
|
) |
const [inline] |
|
bool memoryBlock::is_in_flow_sensitive_list |
( |
flow_sensitive_set & |
flow_sensitive_objects |
) |
|
|
|
Find in flow-sensitivity list.
Return true if the block is identified in the given list. |
bool memoryBlock::is_indexed |
( |
|
) |
const [inline] |
|
bool memoryBlock::is_return_value |
( |
|
) |
const [inline] |
|
bool memoryBlock::is_single_assignment |
( |
|
) |
const [inline] |
|
bool memoryBlock::is_synthetic_decl |
( |
|
) |
const [inline] |
|
bool memoryBlock::is_unify |
( |
|
) |
const [inline] |
|
|
Find the last def in a basic block.
This is used when processing merge (phi function) to find the reaching definition for each input to the merge. It finds the def that dominates the last statement of the basic block. |
procNode* memoryBlock::local_to |
( |
|
) |
const [inline] |
|
|
Process a merge point.
When a merge point is actually encountered, this function returns the list of merge uses (inputs to the phi function), which will have been previously set up by the setup_merge_uses_at() method above. In addition, during the computation of def-use chains, this method finds the reaching def for each merge use (I believe that I've found a clever way to do this). |
string memoryBlock::name |
( |
|
) |
const |
|
|
Find the nearest dominating def.
This requires a dominance-based search through the ordered defs list to determine the nearest dominating definition. It is guaranteed to be unique by the placement of the merge nodes (phi functions). |
void memoryBlock::print |
( |
ostream & |
o, |
|
|
Location * |
path, |
|
|
Output_mode |
mode = CURRENT_VALUE |
|
) |
const |
|
void memoryBlock::print_def_use |
( |
ostream & |
o |
) |
const |
|
static void memoryBlock::print_multiplicity |
( |
Multiplicity |
m, |
|
|
ostream & |
out |
|
) |
[static] |
|
|
Print multiplicity values.
|
void memoryBlock::prune_defs_uses |
( |
|
) |
|
|
|
Reachable blocks.
In the given context, return all of the memoryBlocks reachable by traversing pointers (the closure of the points-to relation). |
void memoryBlock::reset_current_def_use |
( |
Location * |
unused |
) |
|
|
void memoryBlock::set_array_element |
( |
memoryBlock * |
element |
) |
|
|
void memoryBlock::set_current_def_use |
( |
Location * |
where |
) |
|
|
void memoryBlock::set_flow_insensitive |
( |
|
) |
[inline] |
|
void memoryBlock::set_flow_sensitive |
( |
|
) |
[inline] |
|
|
Set flow sensivity.
Check the given list of flow-sensitive objects to see if this block is identified on the list. Depending on the analysis mode, set the flow-sensitivity accordingly. |
void memoryBlock::set_heap_object |
( |
stmtLocation * |
alloc_site |
) |
[inline] |
|
void memoryBlock::set_indexed |
( |
|
) |
[inline] |
|
bool memoryBlock::set_return_value |
( |
|
) |
[inline] |
|
void memoryBlock::set_unification |
( |
UnifyTypes & |
unify_types |
) |
|
|
|
Set unification.
Check the given list of unify objects to see if this block is identified on the list. Depending on the analysis mode, set the flow-sensitivity accordingly. |
void memoryBlock::set_unify |
( |
bool |
flag |
) |
[inline] |
|
void memoryBlock::set_write_protected |
( |
|
) |
[inline] |
|
|
Set up a merge point.
After encountering a def of the memoryBlock, set up the merge uses (inputs to the phi function) at the given merge location. The merge location will be a member of the dominance frontier of the def location. |
void memoryBlock::stats |
( |
ostream & |
out, |
|
|
bool |
header, |
|
|
long int & |
global_defs, |
|
|
long int & |
global_merge_defs, |
|
|
long int & |
global_weak_defs, |
|
|
long int & |
global_uses, |
|
|
long int & |
global_merge_uses |
|
) |
|
|
static void memoryBlock::stats |
( |
|
) |
[static] |
|
|
Top-most container.
Traverse the container chain up to find the top-most container. |
void memoryBlock::unifyType |
( |
UnifyType * |
t |
) |
[inline] |
|
UnifyType* memoryBlock::unifyType |
( |
|
) |
const [inline] |
|
void memoryBlock::update_def_use_chains |
( |
|
) |
|
|
|
Find the nearest interprocedural dominating defCreate a use.
Create a use of the memoryBlock at the given location, if one doesn't already exist. Return the memoryUse object and set the current_use to the use. |
bool memoryBlock::write_protected |
( |
|
) |
const [inline] |
|
Friends And Related Function Documentation
ostream& operator<< |
( |
ostream & |
o, |
|
|
const memoryBlock & |
mb |
|
) |
[friend] |
|
Member Data Documentation
|
Initializer defAllocation object.
This is a pointer to a special memoryBlock that represents the allocation state of heap allocated objects. This object is used for the multiplicity analysis (which is a very sparse analysis problem).
Definition at line 273 of file memoryblock.h. |
|
Complicit assignments.
This map is used by the precision monitor to record complicit assignments: where they occur and the objects that are responsible.
Definition at line 309 of file memoryblock.h.
Referenced by complicit_assignments(). |
|
A list of things contained in this memory block.
Definition at line 153 of file memoryblock.h. |
|
Current def.
This pointer is used during expression evaluation to hold the current def of this block. It is set by the def_at() method. THIS WAS A BUG: we need to at least reset these values when a memoryBlock def leaves a procedure. The reason is that we can leave a procedure at any time (when it converges), which doesn't necessarily leave the most recent def in current_def.
NEW: for flow insensitive objects, we use this field to store the only def (at main).
Definition at line 149 of file memoryblock.h.
Referenced by current_def(). |
|
Current use.
This pointer is used during expression evaluation to hold the current use of this block. It is set by the use_at() method. I'm not sure where (or whether) it should be reset.
NEW: for flow insensitive objects, we use this field to store the only use (at main).
Definition at line 135 of file memoryblock.h.
Referenced by current_use(). |
|
The declaration of this object.
This can be a synthetically created declNode for things that are not explicitly represented (like heap objects).
Definition at line 160 of file memoryblock.h.
Referenced by decl(). |
|
Destructive assignments.
This map is used by the precision monitor to record destructive assignments: where they occur and the cause.
Definition at line 302 of file memoryblock.h.
Referenced by destructive_assignments(). |
|
Only defOnly useInput to.
This set contains all the procedures for which this object is an external input. We need this list for flow-insensitive objects so that we can force reanalysis of those procedures.
Definition at line 295 of file memoryblock.h.
Referenced by input_to(). |
|
Is array.
This flag is set to true if this object is a C array.
Definition at line 181 of file memoryblock.h.
Referenced by is_array(). |
|
Is array element.
This flag is set to true if this object represents the elements of a C array.
Definition at line 188 of file memoryblock.h.
Referenced by is_array_element(). |
|
Is indexed.
This flag is set to true for objects that are indexed (array elements) or any memory that is accessed by pointer arithmetic. Such objects represent more than one actual objects.
Definition at line 196 of file memoryblock.h.
Referenced by is_indexed(), and set_indexed(). |
|
Owner procedure.
For local variables, this points to the procedure that contains the declaration. This allows us to detect non-local access to local variables.
Definition at line 241 of file memoryblock.h.
Referenced by local_to(). |
|
Parameter-assignments.
When this object is an input to a context-insensitive procedure, we merge its state from each of the possible call sites. This map keeps track of the reaching def for each callsite according to the procedure being called. If there is no reaching def, then the memoryDef pointer is null.
Definition at line 124 of file memoryblock.h.
Referenced by parameter_assignments(). |
|
Single assignment.
For flow-insensitive objects, record if there is only one assignment ever made to the object. This helps the adaptive algorithm avoid making too many variables flow sensitive.
Definition at line 227 of file memoryblock.h.
Referenced by is_single_assignment(). |
|
Synthetic declaration flag.
Set to true if the declNode object is synthetic (that is, created just so that there is something to put there). In this case, the destructor will also destroy the declNode.
Definition at line 168 of file memoryblock.h.
Referenced by is_synthetic_decl(). |
|
Unification.
We can control unification on a per-object basis. When this flag is true this object can be unified with another object. The default will be determined by the memoryModel.
Definition at line 219 of file memoryblock.h.
Referenced by is_unify(), and set_unify(). |
|
The uses and defs of this block.
The defs are maintained in the dominating order described in memoryaccess.h. The uses are maintained as a multi-map from the program location to the memoryUse object. It's a multimap because a merge (phi) will return multiple uses.
Definition at line 111 of file memoryblock.h.
Referenced by defs(). |
|
Property handle.
In Broadway, we create special memoryBlocks that represent the value of a particular property. This handle allows us to get from the memoryBlock to the property it represents.
Definition at line 324 of file memoryblock.h. |
|
Property blocks.
Each regular memoryBlock has a vector of pointers to the property blocks.
Definition at line 331 of file memoryblock.h. |
The documentation for this class was generated from the following file:
|