// Copyright 2002 by Keith Vallerio.
// All rights reserved.
/************************************************************
function.cc
Provides support to database.cc. This is one of the major files
in the program. Defines Var, FuncCall and Function classes.
These classes store much of the actual info about the input
source code.
************************************************************/
#include "function.h"
#include "ArgPack.h"
//************************************************************
// Var
//************************************************************
// Constructor
Var::Var (string n, string t, RVector s, long elements) :
name_(n), type_(t), total_size_(-1), num_elements_(elements), stype_(s),
is_pointer_(false), is_static_(false)
{
Rassert(elements >= 0);
MAP (x, s.size()) {
if (s[x] == "pointer") {
is_pointer_ = true;
}
if (s[x] == "static") {
is_static_ = true;
}
}
}
// Determines the size of the variable (type size * number of elements)
void Var::determine_total_size (long type_size)
{
// If it's a pointer, use pre-defined value for pointers
if (is_pointer_) {
total_size_ = ArgPack::ap().pointer_size();
} else {
total_size_ = num_elements_ * type_size;
}
}
//************************************************************
// FuncCall
//************************************************************
// Constructor
FuncCall::FuncCall (string n, long r, long nnode) :
name_(n), parms_(), commas_(0), root_node_(r), fn_name_node_(nnode)
{
}
// Add a dynamic parameter to the func call
void FuncCall::add_parm(pair p)
{
//cout // Rassert(parms_.size() < (commas_ + 1));
if (parms_.size() < (commas_ + 1)) {
while (parms_.size() < commas_) {
parms_.push_back(pair (-1, CONST));
}
parms_.push_back(p);
} else {
long b = parms_.size()-2;
cerr }
}
// Add a comma to keep parameters in correct order
void FuncCall::add_comma()
{
commas_++;
//cout }
// Help keep parameters in order
void FuncCall::balance_commas()
{
//cout while (parms_.size() parms_.push_back(pair (-1, CONST));
}
commas_ = 0;
}
//************************************************************
// Function
//************************************************************
Function::Function (string n, string t, RVector s) :
name_(n), type_(t), stype_(s), parameter_(), variable_(), var_use_(),
action_(), action_type_(), action_tree_node_(),
func_call_(), assign_node_(),
defined_(false), self_dependent_(true), vars_touched_(),
v2v_alias_(), elipses_(false)
{
}
//--------------------------------------------------
// Analysis routines
//--------------------------------------------------
// List of names of all functions called by this function
RVector Function::func_call_names ()
{
RVector call_list;
MAP (x, func_call_.size()) {
call_list.push_back(func_call_[x].name());
}
return call_list;
}
// Add all variables in 'vars' to 'target' alias set
void Function::add_aliases (long target, RVector vars,
bool clear_old_alias)
{
long pointer = target;
if (clear_old_alias) {
Rassert(0);
}
MAP (x, vars.size()) {
v2v_alias_[pointer].insert(vars[x]);
set_union(v2v_alias_[pointer].begin(), v2v_alias_[pointer].end(),
v2v_alias_[vars[x]].begin(), v2v_alias_[vars[x]].end(),
inserter(v2v_alias_[pointer], v2v_alias_[pointer].begin()));
}
// cout }
// Return the indicies of the variables 'v' can alias to.
RVector Function::v_alias_vec (long v)
{
RVector ret_val;
ret_val.push_back(v);
set::iterator i;
set s = v2v_alias_[v];
for (i = s.begin(); i != s.end(); i++) {
long t = *i;
ret_val.push_back(t);
}
return ret_val;
}
// Return the indicies of the parameters of the function
set Function::parameter_set()
{
set ret_val;
MAP (x, parameter_.size()) {
ret_val.insert(parameter_[x]);
}
return ret_val;
}
// Set the variable-to-variable alias vector size.
void Function::init_alias_vectors (long v_size)
{
v2v_alias_.resize(v_size);
}
// Check if 'v' is in 'v_set_num' variable alias set
bool Function::var_in_v_alias (long v, long v_set_num)
{
if ((v2v_alias_[v_set_num].find(v)) != (v2v_alias_[v_set_num].end())) {
return true;
} else {
return false;
}
}
// Remove 'v' from 'v_set_num' variable alias set
void Function::remove_from_v_alias (long v, long v_set_num)
{
set::iterator i = v2v_alias_[v_set_num].find(v);
Rassert(i != v2v_alias_[v_set_num].end());
v2v_alias_[v_set_num].erase(i);
}
// Add all of 'source_num' aliases to the set for 'target_num'
void Function::append_to_v_alias (long target_num, long source_num)
{
set_union(v2v_alias_[target_num].begin(), v2v_alias_[target_num].end(),
v2v_alias_[source_num].begin(), v2v_alias_[source_num].end(),
inserter(v2v_alias_[target_num], v2v_alias_[target_num].begin()));
}
// Return variables aliased to parameters and the arguments themselves
set
Function::func_call_cleanup_aliases (RVector p,
RVector parms)
{
// parms: part of header definition
// p: dynamic parm binding
// Add to dynamic arg alias set based on func_call's effects
MAP(x, p.size()) {
if (p[x].second == VAR) {
// p is a variable arg to func called
MAP (y, parms.size()) {
if (p[y].second == VAR) {
if ((x < parms.size()) && (y < parms.size())) {
// x in y: remove x from y(dynamic) and add x(dynamic)
if (var_in_v_alias(parms[x], parms[y])) {
append_to_v_alias (p[y].first, p[x].first);
remove_from_v_alias (parms[x], p[y].first);
}
}
}
}
}
}
// Prepare a return value encompassing: variables aliased to parms,
// the arguments themselves,
set s;
MAP (x, p.size()) {
if (p[x].second == 0) {
s.insert(p[x].first);
set_union(s.begin(), s.end(),
v2v_alias_[p[x].first].begin(), v2v_alias_[p[x].first].end(),
inserter(s, s.begin()));
}
}
return s;
}
//--------------------------------------------------
// "Function" creation routines
//--------------------------------------------------
// Add a function call to the current function
long Function::add_func_call(string n, long r, long nnode)
{
func_call_.push_back(FuncCall(n, r, nnode));
return (func_call_.size() - 1);
}
// Add a parameter to the current function
void Function::add_parameter (long v)
{
parameter_.push_back(v);
}
// Add a variable to the current function
// (This might not really be useful)
void Function::add_variable(long v)
{
variable_.push_back(v);
}
// Add elipses as a parameter to indicate variable parameters
void Function::add_elipses()
{
elipses_ = true;
}
// Add an argument to a funciton call
void Function::add_func_call_arg (long c, long arg, ArgType arg_type)
{
func_call_[c].add_parm(pair (arg,arg_type));
}
// Add an action (actions defined in tree.cc file)
void Function::add_action (string n, ActionType t, long tn)
{
action_.push_back(n);
action_type_.push_back(t);
action_tree_node_.push_back(tn);
}
// To keep arguments in order
void Function::add_func_call_comma (long fc_num)
{
func_call_[fc_num].add_comma();
}
// To keep arguments in order
void Function::balance_func_call_commas (long fc_num)
{
func_call_[fc_num].balance_commas();
}
//**************************************************
// Printout routines
//**************************************************
ostream &
operator os os os
return os;
}
ostream &
operator MAP (x, vp_a.size()) {
if (vp_a[x].second == VAR) {
os } else if (vp_a[x].second == FUNC) {
os } else
os }
return os;
}
ostream &
operator os os
return os;
}
ostream &
operator os os os os os os os return os;
}