I am trying to write a llvm pass program to count the number of loops within a program. Then I find LoopPass, which is explained in following link:
http://llvm.org/docs/WritingAnLLVMPass.html#the-looppass-class
Three functions are mentioned: doInitialization, runOnLoop, doFinalization.
I originally consider that "doInitialization" runs once at the start of program, "runOnLoop" runs for each time a loop is finished, and "doFinalization" runs at the end of program. I want to define a variable as counter, to be set to "0" in "doInitialization", count++ in "runOnLoop", and output result in "doFinalization".
Here is my code (partial):
virtual bool doInitialization(Loop * L, LPPassManager &LPM)
{
errs() << (*(L->block_begin()))->getParent()->getName() << '\n';
count = 0;
length = 0;
return false;
}
virtual bool runOnLoop(Loop * L, LPPassManager &LPM){
count++;
for(Loop::block_iterator b = L->block_begin(), e = L->block_end(); b != e; b++)
{
length++;
}
return false;
}
virtual bool doFinalization()
{
errs() << "# of loops: " << count << '\n';
errs() << "average depth of loop: " << (float)(length)/count << '\n';
return false;
}
But from the result, "doInitialization" seems to work for number of times equal to number of loops in one function, "runOnLoop" works as expected, "doFinalization" seems to work at the end of a function. So I get two problems:
Why should "doInitialization" works multiple times?
If I want to get the total number of loops within a program (a program may have many functions, I do want "doFinalization" works only once for a program), what should I do?
Thanks to all relative answers,
Why is doInitialization called multiple times?
Counting all loops within the program I would write a ModulePass and overwrite its runOnModule(). Module M you can access all functions (I think the begin and end function should return appropriate iterators).
Then I can use getAnalysis() to get a LoopInfo object for the specified function. That object provides iterators to iterate over all top-level loops. If such a loop contains nested loops all nested loops of the "second level" can be retrieved by using getSubLoops. So for nested loops you would have to use that getSubLoops recursivly until no more subloops exist. Then I could increase some counter for each loop object. So it would look like this (I know that code is not compiling):
int loopcounter;
void handleLoop(Loop *L) {
++loopcounter;
for (Loop *SL : L->getSubLoops()) {
handleLoop(SL);
}
}
virtual bool runOnModule(Module&M) {
loopcounter = 0;
for (auto &IT = M.begin, END = M.end(); IT != END; ++IT) {
LoopInfo &LI = getAnalysis<LoopInfo>(*IT);
for (LoopInfo::iterator LIT = LI.begin(), LEND = LI.end(); LIT != LEND; ++LIT) {
handleLoop(*LIT);
}
}
DEBUG(errs() << "Found " << loopcounter << " loops.\n");
}
To make the getAnalysis call work properly you will have to overwrite the getAnalysisUsage() and add a dependency to LoopInfo by calling AU.addRequired<LoopInfo>().
Because the loop pass is not initialized once for an entire compilation, it's initialized everytime you analyze a loop.
I'd add a debug statement to an existing loop pass that prints something unique, then use grep -c on the output of a compliation with -debug-only=<pass_you_modified>
Related
This is the function that I don't understand:
void showTree (node * tree, int cont) {
if (tree == NULL) {
return;
}
else {
showTree (tree-> right, cont + 1);
for (int i = 0; i <cont; i ++) {
cout << " ";
}
cout << tree-> data << endl;
showTree (tree-> left, cont + 1);
}
}
I do not understand:
How do you get to the for loop if that function is always called recursively?
How are tree items displayed if that function is always called recursively?
If someone could explain to me how this feature works I would really appreciate it.
How do you get to the for loop if that function is always called recursively?
The function returns immediately if tree == NULL, so it may continue onto the for loop.
How are tree items displayed if that function is always called recursively?
The output is produced by the for loop and the next statement, so same reasoning.
I am currently doing games on my free time and am currently working on a hangman game. However, I have stumbled upon a problem and I think I could solve it if there was a way to run a statement if a condition inside a loop is met at least once, and if the condition isn't met even once, it'll do another thing. Is it possible to do? Does anyone have any ideas?
I appreaciate any suggestions.
I tried doing something like this:
for (){
if (string [i] == letter that the player inputed){
// replace underscores with the letter guessed
// and also turn a bool statement true
}
else {
// turn the bool statement false
}
}
if (!bool variable){
// print that the letter guessed was not in the answer
// and substract one from the number of guesses available
}
However I noticed that it doesn't work because the loop will run and if the last letter that it checks is not in the answer, the bool will turn false, thus printing that the letter was not in the answer and substracting one from the score. (It's also my first time posting here, and I don't know if that's how I'm supposed to write a code, so I apologize beforehand if I'm not doing it correctly)
`
You should approach this problem from the different angle:
for( ... ) {
if( your condition is met ) {
do_whatever_you_have_to();
break; // <<--- exit the loop, so it's done only once
}
}
You don't have to put flag guessed off if the comparation fails
string s;
bool guessed = false;
char inputted_letter; // comes from somewhere
for (size_t i = 0; i < s.size(); ++i) {
if (s[i] == inputted_letter) {
// replace underscores with the letter guessed
guessed = true;
}
}
if (!guessed) {
// print that the letter guessed was not in the answer
// and substract one from the number of guesses available
}
You don't have to set false in the loop:
bool has_found = false;
for (auto& c : word_to_guess)
{
if (input_letter == c) {
// replace _ by current letter...
has_found = true;
}
}
if (!has_found){
// print that the letter guessed was not in the answer
// and substract one from the number of guesses available
}
But I suggest that your loop does only one thing at a time:
bool contains(const std::string& word_to_guess, char input_letter)
{
return std::any_of(word_to_guess.begin(),
word_to_guess.end(),
[&](char c){ return input_letter == c; })
/*
for (auto& c : word_to_guess)
{
if (input_letter == c) {
return true;
}
}
return false;
*/
}
if (contains(word_to_guess, input_letter)
{
// show current letter...
for (std::size_t i = 0; i != hangman_word.size(); ++i) {
if (word_to_guess[i] == input_letter) {
hangman_word[i] = word_to_guess[i];
}
}
} else {
// print that the letter guessed was not in the answer
// and substract one from the number of guesses available
}
Can you do what you are asking; possibly, however you stated you were making the game Hangman in C++ and I think you are going about this with the wrong approach, therefore, choosing or implementing the wrong algorithms. You are trying to traverse through two strings with possible different lengths from the back end which if it isn't done correctly can lead to issues, will tend to be hard to track especially if their comparisons determine loop conditions, exit or return statements.
I have implemented my version of "Hangman", now albeit the formatting isn't the prettiest, nor are the level dictionaries being generated from a large pool of random words. I express this in the comments of the code that these would generally be read in from a text file and saved into these structures. For simplicity's sake, I initialized them with random words directly in the code.
Take a look to see what I've done:
#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <random>
class Game;
int main() {
using namespace util;
try {
Game game("Hangman");
game.start();
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
class Game {
private:
std::string title_;
bool is_running_{ false };
std::string answer_;
std::string guessed_;
std::map<unsigned, std::vector<std::string>> dictionary_; // unsigned represents difficulty level of word
unsigned choosen_difficulty_;
std::string guessed_characters_{"\n"};
public:
Game(const std::string& title) : title_{ title }, choosen_difficulty_{ 0 } {
initialize();
start_over();
}
void start() {
is_running_ = true;
// the player has as many attempts as twice the length of hidden answer's word length.
int number_tries = answer_.size() * 2;
while (is_running_ || number_tries > 0) {
displayGuessedWord();
displayGuessedCharacters();
// ask the player to guess a character;
char guess;
// get a character and make sure it is a valid alphabet character
do {
std::cout << "Guess a character ";
std::cin >> guess;
// Note: I'm using ascii characters in this case
// but for demonstration purposes only!
if ((guess < 'a' && guess > 'z') ||
(guess < 'A' && guess > 'Z')) {
std::cout << "invalid entry ";
}
} while ( (guess < 'a' && guess > 'z') ||
(guess < 'A' && guess > 'Z') );
// test character and update guessed word and number of tries.
test_character(guess);
update_guessed_characters(guess);
number_tries--;
// failed condition
if (number_tries <= 0 && guessed_ != answer_) {
std::cout << "\nGame Over!\n";
is_running_ = try_again(number_tries);
// winning condition
} else if (number_tries > 0 && guessed_ == answer_) {
std::cout << "\nCongratulations!\n";
is_running_ = try_again(number_tries);
}
if (!is_running_) break;
}
}
private:
void displayGuessedWord() {
std::cout << '\n' << guessed_ << '\n';
}
void displayGuessedCharacters() {
std::cout << guessed_characters_ << '\n';
}
void initialize() {
// Normally this would be read in from a file upon game initialization
// but for demonstration purpose, I'll generate a few small vectors of strings
// and associate them to their difficulty level
// levels are based on 3 factors, the length of the word, the repetitive occurance
// of common characters, and the amount of less commonly used characters.
std::vector<std::string> level_1{ "ate", "cat", "dog", "coat", "coal", "does" };
std::vector<std::string> level_2{ "able", "believe", "balloon", "better", "funny", "happy" };
std::vector<std::string> level_3{ "ability", "carpenter", "dogmatic", "hilarious", "generosity", "hostility" };
// ... etc. I'll use just these here for simplicty where each vector has six entries, however,
// with random number generators, this can be done generically for any size
// or number of elements in each of the different vectors.
// create generate the map:
dictionary_[1] = level_1;
dictionary_[2] = level_2;
dictionary_[3] = level_3;
}
std::string getWordFromDictionary(unsigned difficulty, std::map<unsigned, std::vector<std::string>>& dict) {
auto level = dict[difficulty]; // extract the vector based on difficulty level
auto size = level.size(); // get the size of that vector
std::random_device dev; // create a random device
std::mt19937 rng(dev()); // create a pseudo random generator
// create a uniform int distribution type with the range from 0 to size-1
std::uniform_int_distribution<std::mt19937::result_type> dist(0, size - 1);
return level[dist(rng)]; // return a random string from this level.
}
void start_over() {
system("cls"); // Note: I'm running visual studio on Windows!
std::cout << "Welcome to " << title_ << '\n';
// We can use a random generator to pick a word from the given difficulty
// but first we need to get user input for the chosen level.
do {
std::cout << "Choose your difficulty [1-3]\n";
std::cin >> choosen_difficulty_;
if (choosen_difficulty_ < 1 || choosen_difficulty_ > 3) {
std::cout << "Invalid entry:\n";
}
} while (choosen_difficulty_ < 1 || choosen_difficulty_ > 3);
answer_ = getWordFromDictionary(choosen_difficulty_, dictionary_);
// clear and resize guessed word to be that of answer_ and add bunch of hypens.
guessed_.clear();
guessed_.resize(answer_.size(), '-');
// also reset the guessed_characters
guessed_characters_ = std::string("\n");
}
bool try_again(int& tries) {
std::cout << "Would you like to try again?\n";
char c;
std::cin >> c;
if (c == 'y' || c == 'Y') {
start_over();
// don't forget to update this so that the loop can repeat
tries = answer_.size() * 2;
return true;
}
else {
std::cout << "Thank you for playing " << title_ << '\n';
return false;
}
}
void test_character(const char c) {
// here is where you would use the standard library for taking the character
// passed into this function, updating the guessed_characters
// get all indexes
std::vector<unsigned> locations;
for (unsigned i = 0; i < answer_.size(); i++)
if (answer_[i] == c)
locations.push_back(i);
// now update the guessed word
if ( locations.size() > 0 )
for (size_t n = 0; n < locations.size(); n++)
guessed_[locations[n]] = c;
}
void update_guessed_characters(const char c) {
guessed_characters_.insert(0, &c); // just push to the front
}
};
If you noticed how I structured the game class above; I am using while and do-while loops in conjunction with for-loops and if-statements and a single boolean flag to determine the state of the game. The game state is also determined from the update to the guessed characters and guessed word. Then I compare that to the answer. Depending on certain conditions the loop will continue seeking input from the user or will exit.
I am not guaranteeing that this code is 100% bug-free for I didn't do any rigorous testing or checking corner cases or special cases but the code has run without error and I've tested all primary game state cases. It appears to be working fine.
I know that there could be many improvements and simplifications made if I had chosen to use some of the standard library functions for working with strings, but I wanted to illustrate the individual steps that are involved in the design or thinking process of making a game with states and their transitions. I could of also put the game class declaration into its own header file with its implementation in a cpp file, but I left that as a single class that is shown in main.cpp for easy copy and paste and compilation.
With this particular game, I did not use a switch and case statements, I just stuck with some while and do-while loops, a few for loops, and if statements since there are only a few game states and transitions to worry about. This implementation also demonstrates the algorithms that are involved and shows how they interconnect with each other. I hope this helps to give you a better understanding of the design process.
When making a game that has different states with a bit of complexity to it, you should start by making your state table first and list all of its transitions before you even write any code. Then you should list your starting, continuing, winning, failing and exiting states or cases. Then you need to draw up how you would transition from one state to another by their required conditions. This will help you in the long run!
Once you have the game state and its transitions laid out properly, then you can start to make your required functions for those states and begin to connect them together. After that is when you would write the internal of the functions or their implementation of what they would do.
Finally, after you have that down is where you want to do some debugging and unit and case testing and if everything appears to be okay, then it would be safe to improve your current algorithms or choosing better ones for peak or most efficient performance.
I would like to know which one would be the best way of using values created inside a loop, outside of that loop. I have for example the function:
void Loop(int a)
{
// recursion loop execution
for ( int i = 0; i < 10; i++ )
{
int new_a = a + i;
}
}
I would like to use that "new_a" as it is being "looped" in another function which is plotting a graph and only needs the "yAxe" value. Like that:
int main ()
{
int a = 5;
plot (x,Loop(int a);
}
I know I could create an array with the values of the loop but I wouldn't like to store them and for big plottings would be too much memory.
Any local variable will be destroyed when the scope of them be finished. For example, in your code new_a will be destroyed when the for loop is finished, and the a is destroyed when the function be finished. I mean if you care about memory, don't be worry.
If I understand you correctly, you want to call Loop multiple times (like e.g. Loop(a)) and each call you should get the next "iteration" of the loop?
That would have been easy if C++ had continuations which it doesn't. Instead it can be emulated by using classes and objects and operator overloading.
For example:
class LoopClass
{
public:
LoopClass(int initial_value = 0)
: current_value{initial_value}
{
}
int operator()(int a)
{
return a + current_value++;
}
private:
int current_value;
};
It can be used as such:
LoopClass Loop; // The value initialized with zero
int a = 5;
std::cout << "First call : " << Loop(a) << '\n';
std::cout << "Second call: " << Loop(a) << '\n';
The above code, if put into a program, should print
First call : 5
Second call: 6
I have a Player class where each object of the type Class has a name, wins, losses, and draws. Each object of the Player class is created by calling the_player = new Player(the_name). When the user inputs a new name to add a Player object to the program a pointer is pushed into a vector AllPlayers. The program should check before pushing the new pointer that the desired player does not already exist in said vector. I have to do this check several times throughout my program so I thought I'd write a function for it. Here is my function:
int findPlayer(vector<Player*> &vals, string name_in)
{
for (int i = 0; i < vals.size(); i++){
if (vals[i]->getName() == name_in){
cout << vals[i]->toString() << endl;
return i;
}
else
return -1;
}
};
When the option is requested to add a new Player the following code is used:
do {
cout << "Name: ";
cin >> the_name;
if (findPlayer(AllPlayers, the_name) != -1){
cerr << "Player already exists\n";
}
} while (findPlayer(AllPlayers, the_name) != -1);
the_player = new Player(the_name);
AllPlayers.push_back(the_player);
For some reason, though, every time I try to add a new player it throws "Player already exists" and never leaves the do-while loop. This is even true when the AllPlayers vector is empty. I added a cout << findPlayer(AllPlayers, the_name) for debugging and it printed 4192252 which I assume is the largest element possible in a vector.
So the question is: Why does it return 4192252 rather than -1?
If vals is empty then the for loop is never entered and the function exits without hitting a return statement. Meaning that you get a random value returned instead, in this case 4192252 happens to be in the return register. Your compiler warnings will have told you this if you read them.
What you think, what will be returned from findPlayer if vals is empty?
Is it defined?
If the vector is empty, you don't enter the loop at all, so don't reach a return statement and don't return a valid value. You should enable compiler warnings to catch this error.
Otherwise, you only check the first item, and return immediately whether or not it matched. You want to return if you find a match, but keep looking otherwise, and only return -1 if there is no match:
for (int i = 0; i < vals.size(); i++){
if (vals[i]->getName() == name_in){
cout << vals[i]->toString() << endl;
return i;
}
}
return -1;
The find player function should be something like:
int findPlayer(vector<Player*> &vals, string name_in)
{
if(vals.size() == 0)
return -1;
for (int i = 0; i < vals.size(); i++){
if (vals[i]->getName() == name_in){
cout << vals[i]->toString() << endl;
return i;
}
}
return -1;
};
Rewrite the function the following way
bool findPlayer( const std::vector<Player*> &vals, const std::string &name_in )
{
std::vector<Player*>::size_tyoe i = 0;
while ( i < vals.size() && vals[i]->getName() != name_in ) ++i;
return i != vals.size();
}
Take into account that member function getName has to be defined with qualifier const.
As for your function then it returns nothing in case when the vector is empty or returns -1 in case when the first element of the vector does not coincide with the string.
Take into account that there is standard algorithm std::find_if declared in header <algorithm> that can be used instead of your function.
I'm new with boost. I have a program which uses dynamic_bitset inside a lambda function. After I try to run the program, I get this message. This message appears even without the function that initializes the bitset and the functions that handle it.
Does anybody know what this message means and what might be the problem?
The message:
/usr/include/boost/dynamic_bitset/dynamic_bitset.hpp:616: boost::dynamic_bitset<Block, Allocator>::~dynamic_bitset() [with Block = long unsigned int, Allocator = std::allocator<long unsigned int>]: Assertion 'm_check_invariants()' failed.
Aborted
well the code is something like this
main call to this function :
int Molecule::initSimilarity(int depth){
cout << "_size is: " << _size << "\t depth is: " << depth << endl; //TODO delete
AtomSet viewing(_size);
int m = 0;
{
// break into initial groups by symbol and valancy
for(int i=0 ; i<_size ; i++)
{
if(viewing[i]) continue;
AtomSet mask = getSetMask( //AtomSet is typedef for dynamic_bitset
[&](const Atom& b)->bool
{
return (!viewing[b._index] && b._valence == _atoms[i]->_valence && strcmp(b._symbol, _atoms[i]->_symbol) == 0);
},
[&](Atom &b)
{
b._class = m; //set the equivalence class of atom 'b' to 'm'
}
);
m++;
viewing |= mask; //viewing now contains a set of atoms and for each atom it's equivalence class
}
cout << "number of equivalence class: " << m << endl; //TODO DELETE!
}
for (int j = 0; j < depth ; j++){
AtomSet viewed(_size);
int before = m;
// iteratively refine the breakdown into groups
for (int i = 0 ; i < _size ; i++) //for any atom A
{
if (viewed[i]) continue;
viewed.flip(i);
AtomSet mask = getSetMask(//put all atoms which are equivalnt but not similar to A in
//their own equivalence class
[&](const Atom& b)->bool
{
if (viewed[b._index])
return false; //if b is in viewed return false;
if (_atoms[i]->_class == b._class) //if in the same class add b to viewed
{
viewed.flip(b._index);
bool similar = !isSimilar(*_atoms[i],b);
return similar;
}
return false;
},
[&m](Atom& b)
{
b._class = m;
}
);
if (!mask.none()) m++;
}
if (before == m){
std::cout << "Finished early after just " << j << " iterations" << std::endl;
return m;
}
}
return m;
}
the signature of getSetMask is:
AtomSet getSetMask(std::function property, std::function action);
and the weirdest thing that even when i remove all the content of that function it still give me the error message
Probably the dynamic_bitset variable that you are referencing in the lambda has gone out of scope and has already been destroyed, or something similar. (Without the source code it's difficult to be more specific)
I had that problem and it took me 3 hours to find out the problem. Here is what can happen: The operator[] in dynamic_bitset does not do bound checking. So, one value can be assigned outside of allowed range and this does not create any error (sanitizer/valgrind do not see anything) since dynamic_bitset is using 64 bit integers (on my computer at least) in order to store values. So, you can get a stored integer of 32 while you allowed only 4 bits in the dynamic_bitset. The error is triggered at a later time when m_check_invariant() is called for example when the destructor is called.
So, the problem becomes to find this range error. The solution is to edit the boost/dynamic_bitset.hpp and add print statement in the code of operator[] when an operation out of range is called. If you cannot do that then download the boost library and install it in your home directory.
I had a similar problem with dynamic_bitset that was solved by calling reset() on it before it got destroyed.
That can indicate that you are writing past the end of the bitset without resizing it. Might want to do some bounds checking.
Read the explaination of Mathieu Dutour Sikiric. The problem is that you write outside of allowed range of the bitset via operator[] and this does not create any error because it's boost and it doesn't bother to waste compute time checking that you have right to write where you want. It is C++ you know...
So to detect it, go to boost/dynamic_bitset/dynamic_bitset.hpp, and modify the code to impose checks every time you use operator[].
boost/dynamic_bitset/dynamic_bitset.hpp, around line 300.
reference operator[](size_type pos) {
assert(m_check_invariants());
return reference(m_bits[block_index(pos)], bit_index(pos));
}
bool operator[](size_type pos) const {
assert(m_check_invariants());
return test(pos);
}
This makes it easier to detect the error in your code.