1 // -*- mode: C++ -*-
2 //
3 // Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 The University of Utah
4 // All rights reserved.
5 //
6 // This file is part of `csmith', a random generator of C programs.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions are met:
10 //
11 //   * Redistributions of source code must retain the above copyright notice,
12 //     this list of conditions and the following disclaimer.
13 //
14 //   * Redistributions in binary form must reproduce the above copyright
15 //     notice, this list of conditions and the following disclaimer in the
16 //     documentation and/or other materials provided with the distribution.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 
30 #if HAVE_CONFIG_H
31 #  include <config.h>
32 #endif
33 
34 #include "Probabilities.h"
35 #include <cassert>
36 #include <fstream>
37 #include <iostream>
38 #include <set>
39 #include <algorithm>
40 #include "StringUtils.h"
41 #include "ProbabilityTable.h"
42 #include "Statement.h"
43 #include "StatementAssign.h"
44 #include "FunctionInvocation.h"
45 #include "Type.h"
46 #include "SafeOpFlags.h"
47 #include "CGOptions.h"
48 #include "MspFilters.h"
49 #include "VectorFilter.h"
50 #include "random.h"
51 
52 ////////////////////////////////////////////////////////////////////////////////////
53 #define VAL_ASSERT(val) assert(((val) <= 100) && ((val) >= -1))
54 
55 using namespace std;
56 
ProbabilityFilter(ProbName pname)57 ProbabilityFilter::ProbabilityFilter(ProbName pname)
58 	: pname_(pname)
59 {
60 
61 }
62 
~ProbabilityFilter()63 ProbabilityFilter::~ProbabilityFilter()
64 {
65 
66 }
67 
68 // only used it for equivalent group
69 bool
filter(int v) const70 ProbabilityFilter::filter(int v) const
71 {
72 	assert(v >= 0);
73 	Probabilities *prob = Probabilities::GetInstance();
74 	assert(prob);
75 	if (prob->check_extra_filter(pname_, v))
76 		return true;
77 
78 	GroupProbElem *elem = dynamic_cast<GroupProbElem*>(prob->probabilities_[pname_]);
79 	assert(elem);
80 	assert(elem->is_equal());
81 
82 	map<ProbName, SingleProbElem *>::iterator i;
83 	bool rv = false;
84 	for (i = elem->probs_.begin(); i != elem->probs_.end(); ++i) {
85 		ProbName pname = (*i).first;
86 		unsigned val = Probabilities::pname_to_type(pname);
87 		if ((static_cast<unsigned int>(v)) == val) {
88 			int prob = (*i).second->get_prob_direct();
89 			rv = (prob == 0);
90 			break;
91 		}
92 	}
93 	return rv;
94 }
95 
96 /////////////////////////////////////////////////////////////////
~ProbElem()97 ProbElem::~ProbElem()
98 {
99 
100 }
101 
102 /////////////////////////////////////////////////////////////////
103 //
104 const char SingleProbElem::single_elem_sep_char = '=';
105 
SingleProbElem(const std::string & sname,ProbName pname,int default_val,int val)106 SingleProbElem::SingleProbElem(const std::string &sname, ProbName pname, int default_val, int val)
107 	: sname_(sname),
108 	  pname_(pname),
109 	  default_val_(default_val),
110 	  val_(val)
111 {
112 
113 }
114 
~SingleProbElem()115 SingleProbElem::~SingleProbElem()
116 {
117 
118 }
119 
120 int
get_prob_direct()121 SingleProbElem::get_prob_direct()
122 {
123 	return val_;
124 }
125 
126 int
get_prob(ProbName pname)127 SingleProbElem::get_prob(ProbName pname)
128 {
129 	// assert(val_ > 0);
130 	assert(pname == pname_);
131 	return val_;
132 }
133 
134 void
set_prob(ProbName pname,int val)135 SingleProbElem::set_prob(ProbName pname, int val)
136 {
137 	assert(pname == pname_);
138 	VAL_ASSERT(val);
139 	if (pname == pVoidProb) {
140 		assert(!val && "Invalid probability - the probability value of void_prob must be 0!");
141 	}
142 	if (val >= 0)
143 		val_ = val;
144 }
145 
146 void
set_prob_table(ProbabilityTable<unsigned int,ProbName> * const)147 SingleProbElem::set_prob_table(ProbabilityTable<unsigned int, ProbName> * const)
148 {
149 	assert(0);
150 }
151 
152 void
dump_default(std::ostream & out)153 SingleProbElem::dump_default(std::ostream &out)
154 {
155 	out << sname_ << single_elem_sep_char << default_val_;
156 }
157 
158 void
dump_val(std::ostream & out)159 SingleProbElem::dump_val(std::ostream &out)
160 {
161 	out << sname_ << single_elem_sep_char << val_;
162 }
163 
164 /////////////////////////////////////////////////////////////////
165 
166 const char GroupProbElem::group_open_delim = '[';
167 const char GroupProbElem::group_close_delim = ']';
168 const char GroupProbElem::group_sep_char = ',';
169 
170 const char GroupProbElem::equal_open_delim = '(';
171 const char GroupProbElem::equal_close_delim = ')';
172 
173 bool
single_elem_less(SingleProbElem * elem1,SingleProbElem * elem2)174 single_elem_less(SingleProbElem *elem1, SingleProbElem *elem2)
175 {
176 	assert(elem1);
177 	assert(elem2);
178 	int val1 = elem1->get_prob_direct();
179 	int val2 = elem2->get_prob_direct();
180 	return (val1 < val2);
181 }
182 
GroupProbElem(bool is_equal,const std::string & sname)183 GroupProbElem::GroupProbElem(bool is_equal, const std::string &sname)
184 	: is_equal_(is_equal),
185 	  sname_(sname)
186 	  // pname_(pname)
187 {
188 
189 }
190 
~GroupProbElem()191 GroupProbElem::~GroupProbElem()
192 {
193 	std::map<ProbName, SingleProbElem*>::iterator i;
194 	for (i = probs_.begin(); i != probs_.end(); ++i) {
195 		SingleProbElem *elem = (*i).second;
196 		assert(elem);
197 		delete elem;
198 	}
199 	probs_.clear();
200 }
201 
202 int
get_random_single_prob(int orig_val,std::vector<unsigned int> & invalid_vals)203 GroupProbElem::get_random_single_prob(int orig_val, std::vector<unsigned int> &invalid_vals)
204 {
205 	// we won't change val if it's disallowed before
206 	if (orig_val == 0) {
207 		return orig_val;
208 	}
209 	if (is_equal_) {
210 		bool p = rnd_flipcoin(50);
211 		return (p ? 1 : 0);
212 	}
213 	else {
214 		VectorFilter f(invalid_vals);
215 		return rnd_upto(101, &f);
216 	}
217 }
218 
219 void
initialize(Probabilities * impl,const std::map<ProbName,int> pairs)220 GroupProbElem::initialize(Probabilities *impl, const std::map<ProbName, int> pairs)
221 {
222 	assert(impl);
223 	std::map<ProbName, int>::const_iterator i;
224 	std::vector<unsigned int> invalid_vals;
225 	invalid_vals.push_back(100);
226 	invalid_vals.push_back(0);
227 	std::vector<SingleProbElem*> valid_probs;
228 
229 	for (i = pairs.begin(); i != pairs.end(); ++i) {
230 		bool valid = false;
231 		int default_val = (*i).second;
232 		int val = default_val;
233 		// make sure val is within the correct range
234 		assert(val >= 0 && val <= 100);
235 		if (CGOptions::random_random()) {
236 			val = get_random_single_prob(val, invalid_vals);
237 			assert(val != 100);
238 			if(val != 0) {
239 				invalid_vals.push_back(val);
240 				valid = true;
241 			}
242 		}
243 		ProbName pname = (*i).first;
244 		std::string sname = impl->get_sname(pname);
245 		SingleProbElem *elem = new SingleProbElem(sname, pname, default_val, val);
246 		probs_[pname] = elem;
247 		if (valid)
248 			valid_probs.push_back(elem);
249 	}
250 
251 	int size = valid_probs.size();
252 	if (CGOptions::random_random()) {
253 		// we can't allow all 0 vals for equal prob group
254 		// if we got one, just use the default settings.
255 		if (is_equal_ && size == 0) {
256 			for (i = pairs.begin(); i != pairs.end(); ++i) {
257 				int val = (*i).second;
258 				assert(val >= 0 && val <= 100);
259 				ProbName pname = (*i).first;
260 				std::string sname = impl->get_sname(pname);
261 				assert(probs_[pname]);
262 				probs_[pname]->set_prob(val);
263 			}
264 		}
265 		else if (!is_equal_) {
266 			assert(size > 0);
267 			int rnd = rnd_upto(size);
268 			valid_probs[rnd]->set_prob(100);
269 		}
270 	}
271 }
272 
273 bool
elem_exist(ProbName pname)274 GroupProbElem::elem_exist(ProbName pname)
275 {
276 	std::map<ProbName, SingleProbElem*>::iterator i = probs_.find(pname);
277 	return (!(i == probs_.end()));
278 }
279 
280 void
set_prob(ProbName pname,int val)281 GroupProbElem::set_prob(ProbName pname, int val)
282 {
283 	assert(elem_exist(pname));
284 	VAL_ASSERT(val);
285 	SingleProbElem *elem = probs_[pname];
286 	assert(elem);
287 	elem->set_prob(pname, val);
288 }
289 
290 int
get_prob(ProbName pname)291 GroupProbElem::get_prob(ProbName pname)
292 {
293 	assert(elem_exist(pname));
294 	SingleProbElem *elem = probs_[pname];
295 	assert(elem);
296 	return elem->get_prob(pname);
297 }
298 
299 void
set_prob_table(ProbabilityTable<unsigned int,ProbName> * const table)300 GroupProbElem::set_prob_table(ProbabilityTable<unsigned int, ProbName> * const table)
301 {
302 	map<ProbName, SingleProbElem*>::iterator i;
303 	for (i = probs_.begin(); i != probs_.end(); ++i) {
304 		SingleProbElem *elem = (*i).second;
305 		assert(elem);
306 		ProbName pname = (*i).first;
307 		int val = elem->get_prob(pname);
308 		// we only care about val > 0 for a probability table
309 		// other value means that we don't put it into the table
310 		if (val > 0)
311 			table->add_elem(static_cast<unsigned int>(val), pname);
312 	}
313 }
314 
315 void
get_all_values(vector<SingleProbElem * > & values)316 GroupProbElem::get_all_values(vector<SingleProbElem*> &values)
317 {
318 	map<ProbName, SingleProbElem*>::iterator i;
319 	for (i = probs_.begin(); i != probs_.end(); ++i)
320 		values.push_back((*i).second);
321 }
322 
323 void
dump_default(std::ostream & out)324 GroupProbElem::dump_default(std::ostream &out)
325 {
326 	char open_delim = is_equal_ ? equal_open_delim : group_open_delim;
327 	char close_delim = is_equal_ ? equal_close_delim : group_close_delim;
328 
329 	out << open_delim << sname_ << group_sep_char;
330 
331 	vector<SingleProbElem*> values;
332 	get_all_values(values);
333 	assert(values.size() >= 1);
334 #if 0
335 	sort(values.begin(), values.end(), single_elem_less);
336 #endif
337 	size_t count = 0;
338 	for (count = 0; count < values.size() - 1; count++) {
339 		values[count]->dump_default(out);
340 		out << group_sep_char;
341 	}
342 	assert(count < values.size());
343 	values[count]->dump_default(out);
344 	out << close_delim;
345 }
346 
347 void
dump_val(std::ostream & out)348 GroupProbElem::dump_val(std::ostream &out)
349 {
350 	char open_delim = is_equal_ ? equal_open_delim : group_open_delim;
351 	char close_delim = is_equal_ ? equal_close_delim : group_close_delim;
352 
353 	out << open_delim << sname_ << group_sep_char;
354 	map<ProbName, SingleProbElem*>::iterator i = probs_.begin();
355 	for (size_t count = 0; count < probs_.size() - 1; count++) {
356 		((*i).second)->dump_val(out);
357 		out << group_sep_char;
358 		++i;
359 	}
360 	assert(i != probs_.end());
361 	((*i).second)->dump_val(out);
362 	out << close_delim;
363 }
364 
365 /////////////////////////////////////////////////////////////////
366 
367 Probabilities* Probabilities::instance_ = NULL;
368 
369 Probabilities *
GetInstance()370 Probabilities::GetInstance()
371 {
372 	if (Probabilities::instance_)
373 		return Probabilities::instance_;
374 
375 	Probabilities::instance_ = new Probabilities();
376 	assert(Probabilities::instance_);
377 	Probabilities::instance_->initialize();
378 	return Probabilities::instance_;
379 }
380 
381 void
DestroyInstance()382 Probabilities::DestroyInstance()
383 {
384 	if (Probabilities::instance_) {
385 		delete Probabilities::instance_;
386 		Probabilities::instance_ = NULL;
387 	}
388 }
389 
390 void
set_single_name(const char * sname,ProbName pname)391 Probabilities::set_single_name(const char *sname, ProbName pname)
392 {
393 	string s = sname;
394 
395 	sname_to_pname_[s] = pname;
396 	pname_to_sname_[pname] = s;
397 }
398 
399 void
set_single_name(const char * sname,ProbName pname,unsigned int type)400 Probabilities::set_single_name(const char *sname, ProbName pname, unsigned int type)
401 {
402 	pname_to_type_[pname] = type;
403 	set_single_name(sname, pname);
404 }
405 
406 #define SET_SINGLE_NAME(s, type, value) \
407 	set_single_name(s, p##type##Prob, e##type); \
408 	m[p##type##Prob] = value;
409 
410 #define SET_SINGLE_NAME1(str, type, value) \
411 	set_single_name(str, p##type##Prob, s##type); \
412 	m[p##type##Prob] = value;
413 
414 void
set_single_name_maps()415 Probabilities::set_single_name_maps()
416 {
417 	// for single probs
418 	// for generating more struct or union types
419 	set_single_name("more_struct_union_type_prob", pMoreStructUnionProb);
420 
421 	set_single_name("bitfields_creation_prob", pBitFieldsCreationProb);
422 
423 	// for single bitfield in a normal struct
424 	set_single_name("bitfield_in_normal_struct_prob", pBitFieldInNormalStructProb);
425 
426 	// for single field in a full-bitfields struct
427 	set_single_name("scalar_field_in_full_bitfields_struct_prob", pScalarFieldInFullBitFieldsProb);
428 
429 	// for single field in exhaustive mode
430 	set_single_name("exhaustive_bitfield_prob", pExhaustiveBitFieldsProb);
431 
432 	// for signed flag of struct/union fields.
433 	set_single_name("bitfields_signed_prob", pBitFieldsSignedProb);
434 
435 	// for signed flag of safe ops
436 	set_single_name("safe_ops_signed_prob", pSafeOpsSignedProb);
437 
438 	// for selecting deref pointer
439 	set_single_name("select_deref_pointer_prob", pSelectDerefPointerProb);
440 
441 	// for regular volatile
442 	set_single_name("regular_volatile_prob", pRegularVolatileProb);
443 
444 	// for regular const
445 	set_single_name("regular_const_prob", pRegularConstProb);
446 
447 	// for stricter const
448 	set_single_name("stricter_const_prob", pStricterConstProb);
449 
450 	// for looser const
451 	set_single_name("looser_const_prob", pLooserConstProb);
452 
453 	// for field
454 	set_single_name("field_volatile_prob", pFieldVolatileProb);
455 
456 	// for field
457 	set_single_name("field_const_prob", pFieldConstProb);
458 
459 	// for std func
460 	set_single_name("std_unary_func_prob", pStdUnaryFuncProb);
461 
462 	// for shift by non constant
463 	set_single_name("shift_by_non_constant_prob", pShiftByNonConstantProb);
464 
465 	// for choosing pointer as LType
466 	set_single_name("pointer_as_ltype_prob", pPointerAsLTypeProb);
467 
468 	// for choosing struct as LType
469 	set_single_name("struct_as_ltype_prob", pStructAsLTypeProb);
470 
471 	// for choosing union as LType
472 	set_single_name("union_as_ltype_prob", pUnionAsLTypeProb);
473 
474 	// for choosing float as LType
475 	set_single_name("float_as_ltype_prob", pFloatAsLTypeProb);
476 
477 	// for creating new array var
478 	set_single_name("new_array_var_prob", pNewArrayVariableProb);
479 
480 	// for wrapping all accesses to a var by ACCESS_ONCE macro
481 	set_single_name("access_once_var_prob", pAccessOnceVariableProb);
482 
483 	// for marking each function as inline
484 	set_single_name("inline_function_prob", pInlineFunctionProb);
485 
486 	// for choosing a builtin function
487 	set_single_name("builtin_function_prob", pBuiltinFunctionProb);
488 
489         //////////////////////////////////////////////////////////////////
490 	// group for statement
491 	set_single_name("statement_prob", pStatementProb);
492 
493 	// group for assignment ops
494 	set_single_name("assign_ops_prob", pAssignOpsProb);
495 
496 	// group for unary ops which equal probability
497 	set_single_name("assign_unary_ops_prob", pUnaryOpsProb);
498 
499 	// group for binary ops which equal probability
500 	set_single_name("assign_binary_ops_prob", pBinaryOpsProb);
501 
502 	// group for simple types which equal probability
503 	set_single_name("simple_types_prob", pSimpleTypesProb);
504 
505 	// group for simple types which equal probability
506 	set_single_name("safe_ops_size_prob", pSafeOpsSizeProb);
507 }
508 
509 void
set_prob_table(ProbabilityTable<unsigned int,ProbName> * const table,ProbName pname)510 Probabilities::set_prob_table(ProbabilityTable<unsigned int, ProbName> *const table, ProbName pname)
511 {
512 	ProbElem *elem = probabilities_[pname];
513 	elem->set_prob_table(table);
514 }
515 
516 unsigned int
pname_to_type(ProbName pname)517 Probabilities::pname_to_type(ProbName pname)
518 {
519 	assert(Probabilities::instance_);
520 
521 	return instance_->pname_to_type_[pname];
522 }
523 
524 int
get_random_single_prob(int orig_val)525 Probabilities::get_random_single_prob(int orig_val)
526 {
527 	// orig_val == 0 means that we disallow it explicitly before,
528 	// so don't change it.
529 	if (orig_val == 0)
530 		return orig_val;
531 	else
532 		return rnd_upto(101);
533 }
534 
535 void
initialize_single_probs()536 Probabilities::initialize_single_probs()
537 {
538 	std::map<ProbName, int> m;
539 	m[pMoreStructUnionProb] = 50;
540 	m[pBitFieldsCreationProb] = 50;
541 	m[pBitFieldInNormalStructProb] = 10;
542 	m[pScalarFieldInFullBitFieldsProb] = 10;
543 	m[pExhaustiveBitFieldsProb] = 10;
544 	m[pBitFieldsSignedProb] = 50;
545 	m[pSafeOpsSignedProb] = 50;
546 
547 	if (CGOptions::volatiles())
548 		m[pRegularVolatileProb] = 50;
549 	else
550 		m[pRegularVolatileProb] = 0;
551 
552 	if (CGOptions::consts())
553 		m[pRegularConstProb] = 10;
554 	else
555 		m[pRegularConstProb] = 0;
556 
557 	if (CGOptions::consts())
558 		m[pStricterConstProb] = 50;
559 	else
560 		m[pStricterConstProb] = 0;
561 
562 	if (CGOptions::consts())
563 		m[pLooserConstProb] = 50;
564 	else
565 		m[pLooserConstProb] = 0;
566 
567 	if (CGOptions::volatiles() &&
568 	    CGOptions::vol_struct_union_fields() &&
569 	    CGOptions::global_variables())
570 		m[pFieldVolatileProb] = 30;
571 	else
572 		m[pFieldVolatileProb] = 0;
573 
574 	if (CGOptions::consts() && CGOptions::const_struct_union_fields())
575 		m[pFieldConstProb] = 20;
576 	else
577 		m[pFieldConstProb] = 0;
578 
579 	m[pStdUnaryFuncProb] = 5;
580 	m[pShiftByNonConstantProb] = 50;
581 	m[pStructAsLTypeProb] = 30;
582 	m[pUnionAsLTypeProb] = 25;
583 	if (CGOptions::enable_float())
584 		m[pFloatAsLTypeProb] = 40;
585 	else
586 		m[pFloatAsLTypeProb] = 0;
587 	if (CGOptions::arrays())
588 		m[pNewArrayVariableProb] = 20;
589 	else
590 		m[pNewArrayVariableProb] = 0;
591 	if (CGOptions::pointers()) {
592 		m[pPointerAsLTypeProb] = 50;
593 		m[pSelectDerefPointerProb] = 80;
594 	}
595 	else {
596 		m[pPointerAsLTypeProb] = 0;
597 		m[pSelectDerefPointerProb] = 0;
598 	}
599 
600 	m[pAccessOnceVariableProb] = 20;
601 	m[pInlineFunctionProb] = CGOptions::inline_function_prob();
602 	m[pBuiltinFunctionProb] = CGOptions::builtin_function_prob();
603 
604 	std::map<ProbName, int>::iterator i;
605 	for (i = m.begin(); i != m.end(); ++i) {
606 		int default_val = (*i).second;
607 		int val = default_val;
608 		assert(val >= 0 && val <= 100);
609 		if (CGOptions::random_random())
610 			val = Probabilities::get_random_single_prob(val);
611 		// For single prob, we don't allow -1 from initialization
612 		ProbName pname = (*i).first;
613 		std::string sname = get_sname(pname);
614 		SingleProbElem *elem = new SingleProbElem(sname, pname, default_val, val);
615 		probabilities_[pname] = elem;
616 	}
617 }
618 
619 void
initialize_group_probs()620 Probabilities::initialize_group_probs()
621 {
622 	set_default_statement_prob();
623 	set_default_unary_ops_prob();
624 	set_default_binary_ops_prob();
625 	set_default_simple_types_prob();
626 	set_default_safe_ops_size_prob();
627 
628 	// setup random distribution of assignment operators (=, +=, /=...)
629 	StatementAssign::InitProbabilityTable();
630 
631 	// setup random distribution of expression term types (const, variable, function ...)
632 	Expression::InitProbabilityTables();
633 }
634 
635 void
set_group_prob(bool is_equal,ProbName pname,const std::map<ProbName,int> & m)636 Probabilities::set_group_prob(bool is_equal, ProbName pname, const std::map<ProbName, int> &m)
637 {
638 	string sname = get_sname(pname);
639 	GroupProbElem *g_elem = new GroupProbElem(is_equal, sname);
640 	g_elem->initialize(this, m);
641 	probabilities_[pname] = g_elem;
642 }
643 
644 void
set_default_safe_ops_size_prob()645 Probabilities::set_default_safe_ops_size_prob()
646 {
647 	std::map<ProbName, int> m;
648 
649 	// each op has equivalent probability
650 
651 	if (CGOptions::int8() && CGOptions::uint8()) {
652 		SET_SINGLE_NAME1("safe_ops_size_int8", Int8, 1);
653 	}
654 	else {
655 		SET_SINGLE_NAME1("safe_ops_size_int8", Int8, 0);
656 	}
657 
658 	SET_SINGLE_NAME1("safe_ops_size_int16", Int16, 1);
659 	SET_SINGLE_NAME1("safe_ops_size_int32", Int32, 1);
660 	if (CGOptions::allow_int64()) {
661 		SET_SINGLE_NAME1("safe_ops_size_int64", Int64, 1);
662 	}
663 	else {
664 		SET_SINGLE_NAME1("safe_ops_size_int64", Int64, 0);
665 	}
666 
667 	set_group_prob(true, pSafeOpsSizeProb, m);
668 	set_prob_filter(pSafeOpsSizeProb);
669 }
670 void
set_default_simple_types_prob()671 Probabilities::set_default_simple_types_prob()
672 {
673 	std::map<ProbName, int> m;
674 
675 	// each op has equivalent probability
676 
677 	// We only use void for function's parameter, so
678 	// disallow choosing void type from other places
679 	SET_SINGLE_NAME("void_prob", Void, 0);
680 	if (CGOptions::int8()) {
681 		SET_SINGLE_NAME("char_prob", Char, 1);
682 	}
683 	else {
684 		SET_SINGLE_NAME("char_prob", Char, 0);
685 	}
686 
687 	SET_SINGLE_NAME("int_prob", Int, 1);
688 	SET_SINGLE_NAME("short_prob", Short, 1);
689 
690 	if (CGOptions::ccomp()) {
691 		SET_SINGLE_NAME("long_prob", Long, 0);
692 		SET_SINGLE_NAME("ulong_prob", ULong, 0);
693 	}
694 	else {
695 		SET_SINGLE_NAME("long_prob", Long, 1);
696 		SET_SINGLE_NAME("ulong_prob", ULong, 1);
697 	}
698 
699 	if (CGOptions::uint8()) {
700 		SET_SINGLE_NAME("uchar_prob", UChar, 1);
701 	}
702 	else {
703 		SET_SINGLE_NAME("uchar_prob", UChar, 0);
704 	}
705 
706 	SET_SINGLE_NAME("uint_prob", UInt, 1);
707 	SET_SINGLE_NAME("ushort_prob", UShort, 1);
708 
709 	if (CGOptions::allow_int64()) {
710 		SET_SINGLE_NAME("long_long_prob", LongLong, 1);
711 		SET_SINGLE_NAME("ulong_long_prob", ULongLong, 1);
712 	}
713 	else {
714 		SET_SINGLE_NAME("long_long_prob", LongLong, 0);
715 		SET_SINGLE_NAME("ulong_long_prob", ULongLong, 0);
716 	}
717 
718 	if (CGOptions::enable_float()) {
719 		SET_SINGLE_NAME("float_prob", Float, 1);
720 	}
721 	else {
722 		SET_SINGLE_NAME("float_prob", Float, 0);
723 	}
724 
725 	set_group_prob(true, pSimpleTypesProb, m);
726 	set_prob_filter(pSimpleTypesProb);
727 }
728 
set_default_unary_ops_prob()729 void Probabilities::set_default_unary_ops_prob()
730 {
731 	std::map<ProbName, int> m;
732 
733 	// each op has equivalent probability
734 	if (CGOptions::unary_plus_operator()) {
735 		SET_SINGLE_NAME("unary_plus_prob", Plus, 1);
736 	}
737 	else {
738 		SET_SINGLE_NAME("unary_plus_prob", Plus, 0);
739 	}
740 
741 	SET_SINGLE_NAME("unary_minus_prob", Minus, 1);
742 	SET_SINGLE_NAME("unary_not_prob", Not, 1);
743 	SET_SINGLE_NAME("unary_bit_not_prob", BitNot, 1);
744 
745 	set_group_prob(true, pUnaryOpsProb, m);
746 	set_prob_filter(pUnaryOpsProb);
747 }
748 
749 void
set_default_binary_ops_prob()750 Probabilities::set_default_binary_ops_prob()
751 {
752 	std::map<ProbName, int> m;
753 
754 	// each op has equivalent probability
755 	SET_SINGLE_NAME("binary_add_prob", Add, 1);
756 	SET_SINGLE_NAME("binary_sub_prob", Sub, 1);
757 
758 	if (CGOptions::muls()) {
759 		SET_SINGLE_NAME("binary_mul_prob", Mul, 1);
760 	}
761 	else {
762 		SET_SINGLE_NAME("binary_mul_prob", Mul, 0);
763 	}
764 
765 	if (CGOptions::divs()) {
766 		SET_SINGLE_NAME("binary_div_prob", Div, 1);
767 	}
768 	else {
769 		SET_SINGLE_NAME("binary_div_prob", Div, 0);
770 	}
771 
772 	SET_SINGLE_NAME("binary_mod_prob", Mod, 1);
773 	SET_SINGLE_NAME("binary_gt_prob", CmpGt, 1);
774 	SET_SINGLE_NAME("binary_lt_prob", CmpLt, 1);
775 	SET_SINGLE_NAME("binary_ge_prob", CmpGe, 1);
776 	SET_SINGLE_NAME("binary_le_prob", CmpLe, 1);
777 	SET_SINGLE_NAME("binary_eq_prob", CmpEq, 1);
778 	SET_SINGLE_NAME("binary_ne_prob", CmpNe, 1);
779 	SET_SINGLE_NAME("binary_and_prob", And, 1);
780 	SET_SINGLE_NAME("binary_or_prob", Or, 1);
781 	SET_SINGLE_NAME("binary_bit_xor_prob", BitXor, 1);
782 	SET_SINGLE_NAME("binary_bit_and_prob", BitAnd, 1);
783 	SET_SINGLE_NAME("binary_bit_or_prob", BitOr, 1);
784 	SET_SINGLE_NAME("binary_bit_rshift_prob", RShift, 1);
785 	SET_SINGLE_NAME("binary_bit_lshift_prob", LShift, 1);
786 
787 	set_group_prob(true, pBinaryOpsProb, m);
788 	set_prob_filter(pBinaryOpsProb);
789 }
790 
791 void
set_default_statement_prob()792 Probabilities::set_default_statement_prob()
793 {
794 	std::map<ProbName, int> m;
795 
796 	// never generate stand-alone blocks
797 	SET_SINGLE_NAME("statement_block_prob", Block, 0);
798 	SET_SINGLE_NAME("statement_ifelse_prob", IfElse, 15);
799 	SET_SINGLE_NAME("statement_for_prob", For, 30);
800 	SET_SINGLE_NAME("statement_return_prob", Return, 35);
801 	SET_SINGLE_NAME("statement_continue_prob", Continue, 40);
802 	SET_SINGLE_NAME("statement_break_prob", Break, 45);
803 	if (CGOptions::jumps() && CGOptions::arrays()) {
804 		SET_SINGLE_NAME("statement_goto_prob", Goto, 50);
805 		SET_SINGLE_NAME("statement_arrayop_prob", ArrayOp, 60);
806 	}
807 	else if (CGOptions::jumps() && !CGOptions::arrays()) {
808 		SET_SINGLE_NAME("statement_arrayop_prob", ArrayOp, 0);
809 		SET_SINGLE_NAME("statement_goto_prob", Goto, 50);
810 	}
811 	else if (!CGOptions::jumps() && CGOptions::arrays()) {
812 		SET_SINGLE_NAME("statement_goto_prob", Goto, 0);
813 		SET_SINGLE_NAME("statement_arrayop_prob", ArrayOp, 55);
814 	}
815 	else {
816 		SET_SINGLE_NAME("statement_goto_prob", Goto, 0);
817 		SET_SINGLE_NAME("statement_arrayop_prob", ArrayOp, 0);
818 	}
819 	// use the remaining probabilities for assignments
820 	SET_SINGLE_NAME("statement_assign_prob", Assign, 100);
821 
822 	set_group_prob(false, pStatementProb, m);
823 }
824 
825 Filter*
get_prob_filter(ProbName pname)826 Probabilities::get_prob_filter(ProbName pname)
827 {
828 	Probabilities *impl = Probabilities::GetInstance();
829 	assert(impl);
830 	Filter *filter = impl->prob_filters_[pname];
831 	if (!filter)
832 		filter = impl->extra_filters_[pname];
833 	assert(filter);
834 	return filter;
835 }
836 
837 void
set_prob_filter(ProbName pname)838 Probabilities::set_prob_filter(ProbName pname)
839 {
840 	prob_filters_[pname] = new ProbabilityFilter(pname);
841 	set_extra_filters(pname);
842 }
843 
844 void
register_extra_filter(ProbName pname,Filter * filter)845 Probabilities::register_extra_filter(ProbName pname, Filter *filter)
846 {
847 	assert(filter);
848 	Probabilities *impl = Probabilities::GetInstance();
849 	assert(impl);
850 	impl->extra_filters_[pname] = filter;
851 }
852 
853 void
unregister_extra_filter(ProbName pname,Filter * filter)854 Probabilities::unregister_extra_filter(ProbName pname, Filter *filter)
855 {
856 	assert(filter);
857 	Probabilities *impl = Probabilities::GetInstance();
858 	assert(impl);
859 	assert(impl->extra_filters_[pname] == filter);
860 	impl->extra_filters_[pname] = NULL;
861 }
862 
863 void
set_extra_filters(ProbName pname)864 Probabilities::set_extra_filters(ProbName pname)
865 {
866 	if (CGOptions::msp()) {
867 		switch(pname) {
868 		case pBinaryOpsProb:
869 			extra_filters_[pname] = new MspBinaryFilter();
870 			break;
871 		default:
872 			break;
873 		}
874 	}
875 }
876 
877 bool
check_extra_filter(ProbName pname,int v)878 Probabilities::check_extra_filter(ProbName pname, int v)
879 {
880 	assert(v >= 0);
881 	std::map<ProbName, Filter*>::iterator i = extra_filters_.find(pname);
882 	if (i != extra_filters_.end() && ((*i).second != NULL))
883 		return (*i).second->filter(v);
884 	else
885 		return false;
886 }
887 
888 // set up default probabilities
889 void
initialize()890 Probabilities::initialize()
891 {
892 	set_single_name_maps();
893 	initialize_single_probs();
894 	initialize_group_probs();
895 }
896 
897 unsigned int
get_prob(ProbName pname)898 Probabilities::get_prob(ProbName pname)
899 {
900 	Probabilities *impl = Probabilities::GetInstance();
901 	ProbElem *elem = impl->probabilities_[pname];
902 	int val = elem->get_prob(pname);
903 
904 	// This assert rules out all invalid accesses to group probs
905 	// and invalid single prob
906 	assert(val >= 0 && val <= 100);
907 	return static_cast<unsigned int>(val);
908 }
909 
910 ProbName
get_pname(const string & sname)911 Probabilities::get_pname(const string &sname)
912 {
913 	std::map<std::string, ProbName>::iterator i = sname_to_pname_.find(sname);
914 	if (i == sname_to_pname_.end())
915 		assert("invalid string in the configuration file:" && sname.c_str() && 0);
916 	return (*i).second;
917 }
918 
919 std::string
get_sname(ProbName pname)920 Probabilities::get_sname(ProbName pname)
921 {
922 	std::map<ProbName, std::string>::iterator i = pname_to_sname_.find(pname);
923 	if (i == pname_to_sname_.end())
924 		assert("invalid string in the configuration file" && 0);
925 	return (*i).second;
926 }
927 
928 bool
parse_configuration(std::string & error_msg,const string & fname)929 Probabilities::parse_configuration(std::string &error_msg, const string &fname)
930 {
931 	ifstream conf(fname.c_str());
932 	if (!conf.is_open()) {
933 		error_msg = "fail to open probabilities configuration file!";
934 		return false;
935 	}
936 
937 	std::string line;
938 	while(!conf.eof()) {
939 		getline(conf, line);
940 		if (StringUtils::empty_line(line))
941 			continue;
942 		if (!parse_line(error_msg, line))
943 			return false;
944 	}
945 	conf.close();
946 	//dump_actual_probabilities();
947 	return true;
948 }
949 
950 bool
setup_group_probabilities(bool is_equal,const vector<string> & elems)951 Probabilities::setup_group_probabilities(bool is_equal, const vector<string> &elems)
952 {
953 	assert(elems.size() > 1);
954 	ProbName pname = get_pname(elems[0]);
955 	ProbElem *elem = probabilities_[pname];
956 	assert(elem);
957 	// Used for sanity check - make sure no two probabilities are the same
958 	set<int> vals;
959 	bool all_zero = true;
960 	bool valid_max_value = false;
961 	for (size_t i = 1; i < elems.size(); i++) {
962 		int val = parse_single_elem(is_equal, elem, elems[i]);
963 		if (is_equal) {
964 			valid_max_value = true;
965 			assert(val == 0 || val == 1);
966 			if (val == 1)
967 				all_zero = false;
968 		}
969 		else {
970 			all_zero = false;
971 			if (val == 100)
972 				valid_max_value = true;
973 			assert(val >= 0 && val <= 100);
974 			if ((val > 0) && (vals.find(val) != vals.end()))
975 				assert("duplicated values in a group probability" && 0);
976 			else
977 				vals.insert(val);
978 		}
979 	}
980 	// assert(vals.size() == (elems.size() - 1));
981 	assert(!all_zero && "Invalid probabilities: all probabilities are zero!");
982 	assert(valid_max_value && "Invalid group probabilities: one probability value must be 100!");
983 	return true;
984 }
985 
986 bool
parse_group_probabilities(bool is_equal,std::string & error_msg,const std::string & line)987 Probabilities::parse_group_probabilities(bool is_equal, std::string &error_msg, const std::string &line)
988 {
989 	string s;
990 	if (is_equal)
991 		s = StringUtils::get_substring(line, GroupProbElem::equal_open_delim, GroupProbElem::equal_close_delim);
992 	else
993 		s = StringUtils::get_substring(line, GroupProbElem::group_open_delim, GroupProbElem::group_close_delim);
994 
995 	if (s.empty()) {
996 		error_msg = "empty group probabilities!";
997 		return false;
998 	}
999 	std::vector<string> elems;
1000 	StringUtils::split_string(s, elems, GroupProbElem::group_sep_char);
1001 	if (elems.size() <= 1) {
1002 		error_msg = "invalid group probabilities format!";
1003 		return false;
1004 	}
1005 	return setup_group_probabilities(is_equal, elems);
1006 }
1007 
1008 int
parse_single_elem(bool is_equal,ProbElem * elem,const std::string & line)1009 Probabilities::parse_single_elem(bool is_equal, ProbElem *elem, const std::string &line)
1010 {
1011 	assert(elem);
1012 	std::vector<std::string> pairs;
1013 	StringUtils::split_string(line, pairs, SingleProbElem::single_elem_sep_char);
1014 	assert(pairs.size() == 2);
1015 	int val = StringUtils::str2int(pairs[1]);
1016 	if (is_equal)
1017 		assert(val == 0 || val == 1);
1018 	else
1019 		assert(val >= 0 && val <= 100);
1020 	ProbName pname = get_pname(pairs[0]);
1021 	elem->set_prob(pname, val);
1022 	return val;
1023 }
1024 
1025 bool
parse_single_probability(std::string &,const std::string & line)1026 Probabilities::parse_single_probability(std::string &, const std::string &line)
1027 {
1028 	std::vector<string> pairs;
1029 	StringUtils::split_string(line, pairs, SingleProbElem::single_elem_sep_char);
1030 	assert(pairs.size() == 2);
1031 
1032 	int val = StringUtils::str2int(pairs[1]);
1033 	VAL_ASSERT(val);
1034 	ProbName pname = get_pname(pairs[0]);
1035 	ProbElem *elem = probabilities_[pname];
1036 	assert(elem);
1037 	elem->set_prob(pname, val);
1038 	return true;
1039 }
1040 
1041 const char Probabilities::comment_line_prefix = '#';
1042 
1043 bool
parse_line(std::string & error_msg,string & line)1044 Probabilities::parse_line(std::string &error_msg, string &line)
1045 {
1046 	char c = StringUtils::first_nonspace_char(line);
1047 	bool rv = false;
1048 	bool is_equal = false;
1049 	if (c == '\0') {
1050 		assert("parse empty line, cannot happen!\n" && 0);
1051 	}
1052 	else if (c == Probabilities::comment_line_prefix) {
1053 		return true;
1054 	}
1055 	else if (c == GroupProbElem::group_open_delim) {
1056 		is_equal = false;
1057 		rv = parse_group_probabilities(is_equal, error_msg, line);
1058 	}
1059 	else if (c == GroupProbElem::equal_open_delim) {
1060 		is_equal = true;
1061 		rv = parse_group_probabilities(is_equal, error_msg, line);
1062 	}
1063 	else {
1064 		rv = parse_single_probability(error_msg, line);
1065 	}
1066 	return rv;
1067 }
1068 
1069 void
dump_default_probabilities(const string & fname)1070 Probabilities::dump_default_probabilities(const string &fname)
1071 {
1072 	assert(!fname.empty());
1073 	ofstream out(fname.c_str());
1074 
1075 	std::map<ProbName, ProbElem*>::iterator i;
1076 	for (i = probabilities_.begin(); i != probabilities_.end(); ++i) {
1077 		(*i).second->dump_default(out);
1078 		out << std::endl << std::endl;
1079 	}
1080 }
1081 
1082 void
dump_actual_probabilities(const string & fname,unsigned long seed)1083 Probabilities::dump_actual_probabilities(const string &fname, unsigned long seed)
1084 {
1085 	assert(!fname.empty());
1086 	ofstream out(fname.c_str());
1087 	out << "# Seed: " << seed << std::endl << std::endl;
1088 
1089 	std::map<ProbName, ProbElem*>::iterator i;
1090 	for (i = probabilities_.begin(); i != probabilities_.end(); ++i) {
1091 		(*i).second->dump_val(out);
1092 		out << std::endl << std::endl;
1093 	}
1094 }
1095 
1096 //////////////////////////////////////////////////////////////////////
Probabilities()1097 Probabilities::Probabilities()
1098 {
1099 
1100 }
1101 
1102 void
clear_filter(std::map<ProbName,Filter * > & filters)1103 Probabilities::clear_filter(std::map<ProbName, Filter*> &filters)
1104 {
1105 	std::map<ProbName, Filter*>::iterator j;
1106 	for (j = filters.begin(); j!= filters.end(); ++j) {
1107 		Filter *f = (*j).second;
1108 		if (f)
1109 			delete f;
1110 	}
1111 	filters.clear();
1112 }
1113 
~Probabilities()1114 Probabilities::~Probabilities()
1115 {
1116 	std::map<ProbName, ProbElem*>::iterator i;
1117 	for (i = probabilities_.begin(); i != probabilities_.end(); ++i) {
1118 		ProbElem *elem = (*i).second;
1119 		assert(elem);
1120 		delete elem;
1121 	}
1122 	probabilities_.clear();
1123 	clear_filter(prob_filters_);
1124 	clear_filter(extra_filters_);
1125 }
1126 
add_entry(int key,int prob)1127 void DistributionTable::add_entry(int key, int prob)
1128 {
1129 	keys_.push_back(key);
1130 	probs_.push_back(prob);
1131 	max_prob_ += prob;
1132 }
1133 
key_to_prob(int key) const1134 int DistributionTable::key_to_prob(int key) const
1135 {
1136 	for (size_t i=0; i<keys_.size(); i++) {
1137 		if (keys_[i] == key) {
1138 			return probs_[i];
1139 		}
1140 	}
1141 	// 0 probablility for keys not found
1142 	return 0;
1143 }
1144 
rnd_num_to_key(int rnd) const1145 int DistributionTable::rnd_num_to_key(int rnd) const
1146 {
1147 	assert(rnd < max_prob_ && rnd >= 0);
1148 	assert(keys_.size() == probs_.size());
1149 	for (size_t i=0; i<probs_.size(); i++) {
1150 		if (rnd < probs_[i]) {
1151 			return keys_[i];
1152 		}
1153 		rnd -= probs_[i];
1154 	}
1155 	assert(0);
1156 	return -1;
1157 }
1158 
1159