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

📄 dbio.cc

📁 C语言前端编译器,yacc/lex编写,可自行修改代码.
💻 CC
📖 第 1 页 / 共 2 页
字号:
// Copyright 2002 by Keith Vallerio.
// All rights reserved.

/************************************************************
  dbio.cc

  Twin file to database.cc.  This file contains DB methods which
are needed for profiling, recompiling and generating a
task graph.
************************************************************/

#include "database.h"
#include "ArgPack.h"
#include <fstream>
#include <map>
#include <set>
#include <algorithm>
#include "ktime.h"

// Class used to temporarily store some annotation information 
// from the start of a loop/cond or function call.  This info
// is then recalled at the end of the loop/cond or func call.
class CallStackItem {
	long tree_node_;
	long source_fn_;
	TimeUnit tu_;
public:
	CallStackItem(long tn, long sf, TimeUnit t);
	long tree_node() { return tree_node_; }
	long source_fn() { return source_fn_; }
	TimeUnit tu() { return tu_; }
};

// Constructor
CallStackItem::CallStackItem (long tn, long sf, TimeUnit t) :
	tree_node_(tn), source_fn_(sf), tu_(t)
{
}

//------------------------------------------------------------
// Profile-related methods
//------------------------------------------------------------

// Recompiles source code.  Uses "kmake.perl".  This should be
// a user-modified script to call a make file or run gcc.  Either
// way, the user should make sure that KSVtime.c is linked in with
// the new executable.
void DB::prof_recompile()
{
	string fname = ArgPack::ap().get_fname();
	string str = "kmake.perl " + fname;
	cout << str << endl;
	system (str.c_str());

// Don't use since some compilations can cause this to fail.
// It would be nice to assert that the compilation succeeded, but
// it must be done some other way...???
//	Rassert (system (str.c_str()) == 0);
}

// Reruns executable.  Removes old data so that it cannot be used
// to give bad results.  Uses "krunner.perl".  This should be a 
// user-modified script to run the executable with appropriate
// input.  This should be a trivial script, but is done this way
// to increase tool flexibility.
void DB::prof_rerun()
{
	system ("rm KSV.out");
	cout << "***Removing KSV.out***\n";
	system ("krunner.perl");

// Don't use since some programs can cause this to fail.
// It would be nice to assert that this succeeded, but
// it must be done some other way...???
//	Rassert (system ("a.out in1 in2") == 0);
}

// Read in data from rerunning new executable.  Use the new info
// to generate edge and node weights for task graph.
void DB::prof_read_data()
{
	ifstream annote_stream;
	RVector<string> vec;
	RVector<long> time_s;
	RVector<long> time_us;
	string s;

	annote_stream.open("KSV.annote");
	Rassert (annote_stream);

	// First read data type sizes.  "KSV" is the flag to indicate
	// this is complete and the next section is starting.
	do {
		getline(annote_stream, s);
		vec = tokenize (s);
		Rassert(!vec.empty());
		if (!(vec[0] == "KSV")) {
			type_map_[vec[0]] = Conv(vec[1]);
		}	
	} while (!(vec[0] == "KSV"));

	// Read data profile times.  Each line is read in as a
	// tokenized string (with 5 components).
	do {
		getline(annote_stream, s);
		vec = tokenize (s);
		if (!vec.empty()) {
			annote_data_.push_back(vec);
		}
	} while (! vec.empty());

	/////////////////////////////////////////////////
	// Use the profile data to get timing info
	// -----------------------------------
	// Each line has 5 parts:
	//    current_function
	//    event (func start/end, loop/cond start/end, statement_end
	//    AST tree node
	//    second   -----\  These are the values from gettimeofday
	//    microsecond --/
	/////////////////////////////////////////////////
	// setup
	TimeUnit t1, t2;	
	t1.set_time(0,0);
	t2.set_time(0,0);
	Rassert(annote_data_[0][1] == "fn_start");

	// Analyze each line from the profile.
	RVector<CallStackItem> fn_stack;
	RVector<CallStackItem> loop_select_stack;
	MAP (x, annote_data_.size()) {
		// 'fn' is the function which the annotation is about
		long fn = func_map(annote_data_[x][0]);
		// 'fname' is the name of that function
		string fname = function_[fn].name();

		// Check function stack.  The item on the top of the stack is
		// the innermost function called.  If 'fn' isn't in that
		// function's call graph, then pop the stack.  Repeat until
		// the 'fn' is inside the current function's call graph.
		// (Another reason to repeat poping is that 'fn' is a
		// reinvocation of the current function.  After popping
		// a function, record how long that function took.
		while (fn_stack.size()) {
			// 'f' is the index of the current function
			// 'new_f' is the same index as 'fn'
			long fn_index = fn_stack.size() - 1;
			long f = fn_stack[fn_index].source_fn();
			long new_f = func_map(annote_data_[x][0]);
			if (call_graph_.in_subtree(f, new_f)) {
				break;
			} else if (new_f == f) {
				if (annote_data_[x][1] != "fn_start") {
					break;
				}
			}

			// If neither condition met, pop this item
			t1 = fn_stack[fn_index].tu();
			t2.set_time(Conv(annote_data_[x][3]), Conv(annote_data_[x][4]));
			fg_[f].set_time_unit(t2-t1);
//			cout << "FTIME: " << function_[f].name() << " " << t2-t1 << endl;
			fn_stack.pop_back();
		}

		// Check loop/cond stack.  The item on the top of the stack is
		// the innermost loop/cond.  If 'new_f' isn't in the current
		// function's ('f') call graph, then pop the stack.  Repeat until
		// the 'f_new' is inside the current function's call graph.
		// After popping a loop/cond, record how long it took.
		while (loop_select_stack.size()) {
			long loop_select_index = loop_select_stack.size() - 1;
			long f = loop_select_stack[loop_select_index].source_fn();
			long new_f = func_map(annote_data_[x][0]);
			if (call_graph_.in_subtree(f, new_f)) {
				break;
			}
			// If neither condition met, pop this item
			t1 = loop_select_stack[loop_select_index].tu();
			t2.set_time(Conv(annote_data_[x][3]), Conv(annote_data_[x][4]));
			set_lc_task_time (
						f, loop_select_stack[loop_select_index].tree_node(), t2-t1);
//			cout << "LC: " << loop_select_stack[loop_select_index].tree_node()
//					<< " " << t2-t1 << endl;
			loop_select_stack.pop_back();
		}

		// record how long a give line took
		if (annote_data_[x][1] == "statement_end") {
			t1.set_time(Conv(annote_data_[x-1][3]), Conv(annote_data_[x-1][4]));
			t2.set_time(Conv(annote_data_[x][3]), Conv(annote_data_[x][4]));
			set_se_task_time (fn, Conv(annote_data_[x][2]), t2-t1);
//			cout << "SE: " << annote_data_[x][2] << " " << t2-t1 << endl;

		} else if (annote_data_[x][1] == "fn_start") {
			long tree_node = Conv(annote_data_[x][2]);
			long f = func_map(annote_data_[x][0]);
			Rassert(f != -1);
			t1.set_time(Conv(annote_data_[x][3]), Conv(annote_data_[x][4]));
			fn_stack.push_back(CallStackItem(tree_node, f, t1));

		// Record preliminary info to later determine length of loop/cond
		} else if ((annote_data_[x][1] == "loop_start") || 
					(annote_data_[x][1] == "select_start")) {
			long tree_node = Conv(annote_data_[x][2]);
			long f = func_map(annote_data_[x][0]);
			Rassert(f != -1);
			t1.set_time(Conv(annote_data_[x][3]), Conv(annote_data_[x][4]));
			loop_select_stack.push_back(CallStackItem(tree_node, f, t1));
		}
	}

	set_all_fc_task_times ();
}

void DB::set_all_fc_task_times ()
{
	Rassert(fg_.size() == function_.size());
	MAP (x, function_.size()) {
		RVector<long> func_node = fg_[x].func_call_nodes();
		MAP (y, func_node.size()) {
			TimeUnit tu;
			tu.set_time(0,0);
			RVector<long> call_list = fg_[x][func_node[y]].func();

			MAP (z, call_list.size()) {
				long fc_num = call_list[z];
				TimeUnit t2 = fg_[fc_num].time_unit();
				tu = tu + t2;
			}
			fg_[x][func_node[y]].set_time_unit(tu.sec(), tu.usec());
		}
	}
}

// set statement end node times
void DB::set_se_task_time (long f, long tree_node, TimeUnit t)
{
	long n = fg_[f].find_se_node(tree_node);
	Rassert(n != -1);
	TimeUnit old_t = fg_[f][n].time_unit();

	// keep worst-case time
	if (old_t < t) {
		fg_[f][n].set_time_unit(t.sec(), t.usec());
	}
}

// set loop/cond node times
void DB::set_lc_task_time (long f, long tree_node, TimeUnit t)
{
	long n = fg_[f].find_lc_node(tree_node);
	Rassert(n != -1);
	TimeUnit old_t = fg_[f][n].time_unit();

	// keep worst-case time
	if (old_t < t) {
		fg_[f][n].set_time_unit(t.sec(), t.usec());
	}
}

// Determine node edge sizes based on profile info.
void DB::prof_get_arc_lengths()
{
	//--------------------------------------------------
	// Determine sizes for each variable!!!
	//--------------------------------------------------
	MAP (x, variable_.size()) {
		string type_name = variable_[x].type();
		long type_size;
//cout << variable_[x].name() << " " << variable_[x].type();

		// unknown variables' types are set equal to pointer size
		if (type_map_.find(type_name) == type_map_.end()) {
			type_size = ArgPack::ap().pointer_size();
		} else {
			type_size = type_map_[type_name];
		}
		variable_[x].determine_total_size(type_size);
//		cout << " " << variable_[x].total_size() << endl;
	}

⌨️ 快捷键说明

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