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