⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 database.cc

📁 C语言前端编译器,yacc/lex编写,可自行修改代码.
💻 CC
📖 第 1 页 / 共 2 页
字号:
						fg[n].add_var_mod(vm);
						lhs_var.push_back(get_assign_lhs_var(id,assign[assign_num]));
						assign_num++;
						assign_ctr--;
					}
					update_lhs_var_aliases(id, lhs_var);
					n = fg.get_new_node(id);
				}
				break;
			case STATE_NUM:
				break;
			case BRAC_OPEN:
break;//KSV
				fg[n].add_action(s,tn);
				brac_stack.push_back(n);
				break;
			case BRAC_CLOSE:
break;//KSV
				fg[n].add_action(s,tn);
				tmp = brac_stack[brac_stack.size() - 1];
				if (tmp != n) {
					for (long i = tmp+1; i <= n; i++) {
						fg.add_edge (i, tmp, Edge(-10000));
					}
				}
				brac_stack.pop_back();
				if (!block_depth) n = fg.get_new_node(id);
				break;
			case FN_START:
//				cout << function_[id].func_call()[fc_num];
				if (!block_depth) n = fg.get_new_node(id);
				fg[n].add_action(s,tn);
				func_node_stack.push_back(n);
				vm = do_func_call(id, fc_num);
				fc_func = func_map(((function_[id].func_call())[fc_num]).name());
				fg[n].add_func(fc_func);
				if (!function_[fc_func].defined()) {
					set<long> vt;
					vt.insert(0);
					function_[fc_func].set_vars_touched(vt);
					fg[n].add_var_mod(0);
					vm.push_back(0);		
				}
				fg[n].add_var_mod(vm);
				fc_num++;
				break;
			case FN_END:
				fg[n].add_action(s,tn);
				tmp = func_node_stack[func_node_stack.size() - 1];
				if (tmp != n) {
					for (long i = tmp+1; i <= n; i++) {
						fg.add_edge (i, tmp, Edge(-10000));
					}
				}
				func_node_stack.pop_back();
				if (!block_depth) n = fg.get_new_node(id);
				break;
		}

		// Post processing for assignments:
		// If an assign end is reached and we aren't inside a
		// loop/cond, draw edges to represent assign data dependencies.
		if (draw_assign_arcs) {
			if (!block_depth) {
				Rassert(assign_target != -1);
				for (long i = assign_target + 1; i < n; i++) {
					fg.add_edge(i, assign_target, Edge(-10000));
				}
				vm = add_alias_data(id, assign[assign_num++]);
				fg[assign_target].add_var_mod(vm);
				assign_ctr--;
//				assign_ctr = 0;
			}
			if (!assign_ctr) {
				assign_target = -1;
			}
		}
	}
	///////////////////////////////////
	// function dependence cleanup
	///////////////////////////////////
	// finish drawing edges in dependence graph
	fg.make_depend_arcs();
	// remove/merge nodes to simplify graph
	fg.compact_graph();

	// Determine which variables would be used/modified during
	// a call to this function.  Currently, assumes that any variable
	// used would be modified as well.
	fg.find_tree_node_starts();
	set<long> vars_touched = fg.determine_vars_touched();
	set<long> new_touched;
//	cout << function_[id].name() << ":  " << vars_touched << endl;
	set_difference(vars_touched.begin(), vars_touched.end(),
						local_vars.begin(), local_vars.end(),
						inserter(new_touched, new_touched.begin()));
	vars_touched = new_touched;

// KSV remove this set difference for stricter analysis
	if (!(ArgPack::ap().strict_dependence())) {
		new_touched.clear();
		set<long> parm_set = function_[id].parameter_set();
		set_difference(vars_touched.begin(), vars_touched.end(),
						parm_set.begin(), parm_set.end(),
						inserter(new_touched, new_touched.begin()));
		vars_touched = new_touched;
	}

//	cout << function_[id].name() << ":  " << vars_touched << endl;
//	if (function_[id].name() == "print_array") {
//		cout << "STUFF: " << vars_touched << endl;
//	}

	// Finally, record variables which are used by this function
	function_[id].set_vars_touched(vars_touched);
	return fg;
}

// Do analysis for a function call by 'id' to whichever function is
// the target of func call number 'fc_num'.  Note: 'fc_num' is NOT
// the number of the callee, rather it is the X'th function call
// invoked by function 'id'!
RVector<long> DB::do_func_call (long id, long fc_num)
{
	// Get callee function index and store in 'func'
	FuncCall fc = function_[id].func_call()[fc_num];
	long func = func_map(fc.name());

	// 2 types of parms: static (in function header)
	//                   call_time (in current function invocation)
	RVector<long> static_parms = function_[func].parameter();
	RVector<pair<long,ArgType> > call_time_parms = fc.parms();

	RVector<long> ret_val;
	set<long> arg_fc_vars;

	// DEBUG STUFF: for when the 2 parms sizes are not equal
//cout << "caller: " << function_[id].name() << "  ";
//cout << fc.name() << "  " << call_time_parms.size() << "  " 
//		<< static_parms.size() << endl;
	if (call_time_parms.size() != static_parms.size()) {
//		if (!(ArgPack::ap().loosest_dependence())) {
			Rassert(!(function_[func].defined()));
//		}
//		Rassert(function_[func].elipses());
	}

	// Analyze function call parameters:
	//    Parameters could be function calls, constants or variables
	MAP(x, call_time_parms.size()) {
		if (call_time_parms[x].second == FUNC) {
			// Handle nested function calls
			// they should return which vars they touch
			// Add those variables to ret_val
			set<long> tset = function_[call_time_parms[x].first].vars_touched();
			set_union(arg_fc_vars.begin(), arg_fc_vars.end(),
							tset.begin(), tset.end(),
							inserter(arg_fc_vars, arg_fc_vars.begin()));

		} else if (call_time_parms[x].second == CONST) {
			// do nothing for consts

		} else if (variable_[call_time_parms[x].first].is_pointer()) {
			// update aliases based on parameters which are variables
			if (x < static_parms.size()) {
				RVector<long> p_alias=function_[func].v_alias_vec(static_parms[x]);
				function_[id].add_aliases (call_time_parms[x].first,p_alias,false);
			}
		}
	}

	///////////////////////////////////////
	// Prepare return value (vars touched)
	///////////////////////////////////////
	// 'parm_set' is indicies of function's static parameters
	set<long> parm_set = function_[func].parameter_set();
   // Returns value encompassing: variables aliased to parms,
   //    and the arguments themselves
	set<long> tmp = function_[id].func_call_cleanup_aliases (
													call_time_parms, static_parms);
	// variables touched inside the function
	set<long> v_touched = function_[func].vars_touched();
	set<long> ret_set;

	// combine the sets to get the set of vars touched
	set_union(arg_fc_vars.begin(), arg_fc_vars.end(),
					tmp.begin(), tmp.end(), inserter(tmp, tmp.begin()));
	set_union(v_touched.begin(), v_touched.end(),
					tmp.begin(), tmp.end(), inserter(tmp, tmp.begin()));

// KSV remove this set difference for stricter analysis
	if (!(ArgPack::ap().strict_dependence())) {
		set_difference(tmp.begin(), tmp.end(),	parm_set.begin(), parm_set.end(),
						inserter(ret_set, ret_set.begin()));
	} else {
		ret_set = tmp;
	}

	// convert set to vector
	set<long>::iterator i;
	for (i = ret_set.begin(); i != ret_set.end(); i++){
		long t = *i;
		ret_val.push_back(t);
	}

	return ret_val;
}

// Determine alias effects for a given assignment.
//       'fn' is the function, 
//       'a_node' gives the boundaries of the assignment
// Note: This function should handle multiple assignments in a
//       single line appropriately.
RVector<long> DB::add_alias_data (long fn, pair<long,long> a_node)
{
	long start = a_node.first;  // first AST node of assignment
	long end = a_node.second;   // last AST node of assignment
	long target = -1, assign_op = -1;
	bool clear_old_alias = false;  // not used
	RVector<long> v;
	string str;

	//-----------------------------------------------------
	// Walk through assignment from first AST node to end.
	// First variable is the target (the first if condition).
	// Next wait to grab an assignment operator. (condition 2 & 3)
	// Finally, all vars on RHS of assign operator are sources (cond 4)
	//-----------------------------------------------------
	for (long i = start; i < end; i++) {
		str = create_var_name (tree_node_[i].name(), fn);
		if (target == -1) {
			// Only grabs first var on left of '=' sign
			// this allows it to only get the 'a' in 'a[i]' statements
			// NOTE: If variable is not in map 'var_map' returns '-1'
			target = get_literal_id (str);
		} else if (tree_node_[i].name() == "assignment_operator") {
			assign_op = i;
// Perhaps one could clear old aliases, but you would have to do 
// control flow checking first so it isn't performed currently...
//KSV				clear_old_alias = true;
		} else if ((tree_node_[i].name() == ">>=") ||
					(tree_node_[i].name() == "<<=") ||
					(tree_node_[i].name() == "+=") ||
					(tree_node_[i].name() == "-=") ||
					(tree_node_[i].name() == "*=") ||
					(tree_node_[i].name() == "/=") ||
					(tree_node_[i].name() == "%=") ||
					(tree_node_[i].name() == "&=") ||
					(tree_node_[i].name() == "^=") ||
					(tree_node_[i].name() == "|=")) {
			assign_op = i;
		} else if (assign_op > -1) {
			long a = get_literal_id(str);
			if (a != -1) {
				v.push_back(a);
			}
		}
	}

	// If it was an assignment, it must have had a target.
	Rassert(target != -1);

	// If the target was a pointer add to it's alias set
	if (variable_[target].is_pointer()) {
		function_[fn].add_aliases (target, v, clear_old_alias);
	}

	// Return the alias vector of the target variable
	return (function_[fn].v_alias_vec(target));
}

// Gets the target of the assignment specified by 'a_node'.
// (The target would be the left most variable.)
long DB::get_assign_lhs_var (long fn, pair<long,long> a_node)
{
	long start = a_node.first, end = a_node.second;
	long target = -1;
	for (long i = start; i < end; i++) {
		string str = create_var_name (tree_node_[i].name(), fn);
		if (target == -1) {
			// Only grabs first var on left of '=' sign
			// this allows it to only get the 'a' in 'a[i]' statements
			// NOTE: If variable is not in map 'var_map' returns '-1'
			target = get_literal_id (str);
		}
		if (target != -1) {	
			return target;
		}
	}
	Rabort();
	return -1;
}

// Give each var in 'lhs_var' the aliases of all the others
void DB::update_lhs_var_aliases (long id, RVector<long> lhs_var)
{
	set<long> s;
	MAP (x, lhs_var.size()) {
		set<long> vs = function_[id].v2v_alias_var(lhs_var[x]);
		set_union(s.begin(), s.end(), vs.begin(), vs.end(),
				inserter(s, s.begin()));
	}
	MAP (x, lhs_var.size()) {
		function_[id].set_v2v_alias_vec(lhs_var[x], s);
	}
}

/*===========================================================================*/
// Output routines
/*===========================================================================*/
// Generates the vcg file to view the call graph
void DB::print_fgraph_vcg ()
{
	ofstream out;
	string file_name = "call_graph.vcg";
	out.open(file_name.c_str());

	if (!out) {
		cout << "Cannot open output file";
		Rabort();
	}

	out << "graph: { label: \"" << file_name << "\"\n";
	out << "display_edge_labels: no\n";

	call_graph_.print_vcg_inside(out);
	

	out << "}\n";
}

// Generates the vcg file to view the task graphs for each function
void DB::print_tgraph_vcg ()
{
	ofstream out;

	// create subdirectory to put vcg files in
	string dir_name = "tmp_vcg";
	string sysstr = "mkdir " + dir_name;
	system(sysstr.c_str());

	// For each function which contains nodes, create a vcg file
	MAP (x, fg_.size()) {
		if (fg_[x].size_vertex()) {
			string s = "tmp_vcg/" + fg_[x].name();
			out.open(s.c_str());
			Rassert(out);

			out << "graph: { label: \"" << s << "\"\n";
			if (ArgPack::ap().display_edge_labels()) {
				out << "display_edge_labels: yes\n";
			} else {
				out << "display_edge_labels: no\n";
			}
			fg_[x].print_vcg_inside(out);
			out << "}\n";
			out.close();
		}
	}
}

// output some database info...(Not used)
ostream &
operator<<(ostream & os, const DB & db_a) {
	os << "Functions:\n";
	MAP (x, db_a.size_function()) {
		os << db_a.function(x) << endl;
	}
	os << "Variables:\n";
	MAP (x, db_a.size_variable()) {
		os << db_a.variable(x) << endl;
	}
	return os;
}

// output method for a set of longs...
ostream &operator <<(ostream &output, set<long> &sa)
{
	set<long>::iterator i;
	for (i = sa.begin(); i != sa.end(); i++) {
		output << *i << " ";
	}
	return output;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -