Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for computed goto extension #61

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion src/Block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
#include "Expression.h"
#include "VectorFilter.h"

#include <string>
#include <vector>
using namespace std;

///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -188,14 +190,40 @@ Block::make_random(CGContext &cg_context, bool looping)

curr_func->stack.pop_back();
if (Error::get_error() != SUCCESS) {
//curr_func->stack.pop_back();
curr_func->stack.pop_back();
delete b;
return NULL;
}

// ISSUE: in the exhaustive mode, do we need a return statement here
// if the last statement is not?
Error::set_error(SUCCESS);


if(CGOptions::computed_goto()){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, we should not modify the AST nodes contained in a block once the block is fully generated. I suggest we collect addr_labels and create the alternative label based on index in the addr_labels inside StatementGoto::make_random.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I collected addr_labels in StatementGoto::make_random and created alternate label for it. After adding above, I am getting error like some labels are used but not defined. Is it because the generated block is discarded?

for example - in a particular block

{
void *target[] = { &&lbl_123, &&lbl_456};
}

&&lbl_456 is alternate label when lbl_456 is generated. But it is not present in that block, which stats label used but not defined.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your point. What about we still do a generation of the computed goto labels after a block is generated, i.e., at the same place in block.cpp, but instead of modifying the StatementGoto nodes, we put the alternative labels in an external data structure? For example, this could be an additional static map in StatemenGoto.h other than stm_labels where each target of the goto-statements is associated with an alternative label.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above patch does the same. It creates alternate labels after a block is created but do not alter current labels.

I am facing difficulty in understanding implementation of stm_labels in goto::make_random. As per my understanding, stm_labels is map in which source contains goto statement and destination contain respective label.

Can you elaborate about stm_labels?

Also, we are unsure which labels will be there in final block. Even if we created alternative label, for the computed goto extension, below approach is followed.

{
void *target[] = { &&lbl_123, &&lbl_456};

goto *target[0];
}

At the end we want label present in target array. So, basically alternate labels are stored inside addr_label of every block. Do we still need static map in StatementGoto.h ? We can use addr_label to generate goto destination in block make::random

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Csmith, the make_random functions defined in various classes generate an AST node of the class. StatementGoto::make_random generates a goto-statement, and if we add alt_label as a field to StatementGoto, we expect alt_label not to be altered AFTER StatementGoto::make_random is called.

stm_labels maps all destinations of goto-statement (as a Statement*) to their labels. It's there to avoid we assign two labels to the same destination.

addr_label stores labels for a given block. The static map in StatementGoto.h would map all destinations of goto-statement (as Statement*) to their alternative labels in the whole program. This static map is not part of the StatementGoto object (the AST node), thus we are fine to modify it after the block is finalized.

if(curr_func->blocks[0]->stm_id==b->stm_id){
std::vector<string> labels;
labels.clear();
curr_func->blocks[0]->find_contained_labels(labels);
string ss="";
for (std::vector<string>::iterator itr=labels.begin();itr!=labels.end();itr++) {
ss.clear();
ss += "&&";
ss += *itr;
curr_func->blocks[0]->addr_labels.push_back(ss);//only adds in the main array related to function.
}
//__________________________________________________________
for (size_t i=0; i<fm->cfg_edges.size();i++) {
const CFGEdge* e = fm->cfg_edges[i];
if(e->src->eType == eGoto) {
const StatementGoto* sg = dynamic_cast<const StatementGoto* >(e->src);
assert(sg);
sg->change_label(curr_func->blocks[0]->addr_labels);
}
}

}
}
return b;
}

Expand Down Expand Up @@ -295,6 +323,10 @@ Block::Output(std::ostream &out, FactMgr* fm, int indent) const
ss << "block id: " << stm_id;
output_comment_line(out, ss.str());

if(CGOptions::computed_goto()){
if(!this->addr_labels.empty())
this->print_label_addr_array(out,indent);
}
if (CGOptions::depth_protect()) {
out << "DEPTH++;" << endl;
}
Expand Down Expand Up @@ -805,6 +837,19 @@ Block::post_creation_analysis(CGContext& cg_context, const Effect& pre_effect)
}
}

void
Block::print_label_addr_array(std::ostream &out , int indent) const{
ostringstream ss;
output_tab (out,indent);
cout << "/*\nNUMBER OF GOTO'S IN ABOVEE BLOCK:" << addr_labels.size() << "*\/";
cout << "\nvoid *target[] = { ";
for(unsigned int i=0; i < addr_labels.size();i++){
i!=0 ? cout << ", " : cout << "";
cout << addr_labels[i];
}

cout << "};\n";
}
///////////////////////////////////////////////////////////////////////////////

// Local Variables:
Expand Down
3 changes: 3 additions & 0 deletions src/Block.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ class Block : public Statement
Block* random_parent_block(void);

int block_size() { return block_size_; }
std::vector<string> addr_labels;
void print_label_addr_array(std::ostream&, int) const;

// These are currently accessed directly.
std::vector<Statement *> stms;
std::vector<Statement *> deleted_stms;
Expand Down
2 changes: 2 additions & 0 deletions src/CGOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ DEFINE_GETTER_SETTER_BOOL(const_struct_union_fields);
DEFINE_GETTER_SETTER_BOOL(lang_cpp);
DEFINE_GETTER_SETTER_BOOL(cpp11);
DEFINE_GETTER_SETTER_BOOL(fast_execution);
DEFINE_GETTER_SETTER_BOOL(computed_goto);

void
CGOptions::set_default_builtin_kinds()
Expand Down Expand Up @@ -313,6 +314,7 @@ CGOptions::set_default_settings(void)
fast_execution(false);

set_default_builtin_kinds();
computed_goto(false);
}

// Add options necessary for cpp
Expand Down
3 changes: 3 additions & 0 deletions src/CGOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,8 @@ class CGOptions {
static bool signed_char_index(void);
static bool signed_char_index(bool p);

static bool computed_goto(void);
static bool computed_goto(bool p);
/////////////////////////////////////////////////////////
static void set_default_settings(void);

Expand Down Expand Up @@ -579,6 +581,7 @@ class CGOptions {
static bool no_return_dead_ptr_;
static bool hash_value_printf_;
static bool signed_char_index_;
static bool computed_goto_;
static std::string dump_default_probabilities_;
static std::string dump_random_probabilities_;
static std::string probability_configuration_;
Expand Down
1 change: 0 additions & 1 deletion src/DefaultProgramGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ void
DefaultProgramGenerator::goGenerator()
{
output_mgr_->OutputHeader(argc_, argv_, seed_);

GenerateAllTypes();
GenerateFunctions();
output_mgr_->Output();
Expand Down
13 changes: 13 additions & 0 deletions src/RandomProgramGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ static void print_help()
cout << " --inline-function | --no-inline-function: enable | disable inline attributes on generated functions." << endl << endl;
cout << " --inline-function-prob <num>: set the probability of each function being marked as inline (default is 50)." << endl << endl;

//GCC C extensions
cout << " --computed-goto | --no-computed-goto: enable | disable computed goto extension (disable by default)." << endl << endl;

// numbered controls
cout << " --max-array-dim <num>: limit array dimensions to <num>. (default 3)" << endl << endl;
cout << " --max-array-len-per-dim <num>: limit array length per dimension to <num> (default 10)." << endl << endl;
Expand Down Expand Up @@ -850,6 +853,16 @@ main(int argc, char **argv)
continue;
}

if (strcmp (argv[i], "--computed-goto") == 0) {
CGOptions::computed_goto(true);
continue;
}

if (strcmp (argv[i], "--no-computed-goto") == 0) {
CGOptions::computed_goto(false);
continue;
}

if (strcmp (argv[i], "--no-jumps") == 0) {
CGOptions::jumps(false);
continue;
Expand Down
27 changes: 26 additions & 1 deletion src/StatementGoto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,11 @@ StatementGoto::Output(std::ostream &out, FactMgr* /*fm*/, int indent) const
out << ")";
outputln(out);
output_tab(out, indent+1);
out << "goto " << label << ";";

if(CGOptions::computed_goto())
out << "goto " << other_name_for_label << ";";
else
out << "goto " << label << ";";
outputln(out);
}

Expand Down Expand Up @@ -416,6 +420,27 @@ StatementGoto::doFinalization(void)
stm_labels.clear();
}

void
StatementGoto::change_label(std::vector<string> addr_labels) const{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function creates an alternative label for the goto statement. Rename it accordingly.

string find_label="";
find_label+="&&";
find_label+=label;
auto it = std::find(addr_labels.begin(),addr_labels.end(),find_label);
int index;
if(it == addr_labels.end()){
assert ("LABEL NOT FOUND");
}
else{
index = std::distance (addr_labels.begin(),it);
}
std::stringstream ss;
ss.clear();
ss<< "*target[";
ss<<index;
ss<<"]";
other_name_for_label="";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too verbose. For example line 437 to 440 can be rewritten as ss << "*target[" << index << "]

other_name_for_label=ss.str();
}
///////////////////////////////////////////////////////////////////////////////

// Local Variables:
Expand Down
3 changes: 3 additions & 0 deletions src/StatementGoto.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class StatementGoto : public Statement
std::string label;
std::vector<const Variable*> init_skipped_vars;
static std::map<const Statement*, std::string> stm_labels;

mutable std::string other_name_for_label;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

other_name_for_label no longer needs to be mutable once we adopt the approach that creates alternative label while a goto statement is being created.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without mutable keyword, it is not possible to assign constant string to other_name_for_label. Is there any other approach to remove mutable keyword?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we move the alternative label to a map like I suggested above, we don't need this field anymore.

void change_label(std::vector<string> addr_labels) const;
};

///////////////////////////////////////////////////////////////////////////////
Expand Down