I have been using
opt -stats -analyze -instcount file.bc
to get statistic info of code. Now I would like to get the number of the LLVM instructions in a function of a particular name, say, "bar".
Ideally, I would expect an option of opt, which would work in this way
opt -stats -analyze -instcount funcname="bar"
What would be the right option to use? I googled a lot and have not got an answer yet.
Create a function analysis pass. (llvm::FunctionPass documentation)
Your code would look something like this:
// This is a contrived example.
#include <iterator>
#include <string>
#include "llvm/Pass.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instruction.h"
#include "llvm/Support/raw_ostream.h"
namespace
{
using namespace llvm;
cl::opt<std::string> functionName("funcname", cl::ValueRequired,
cl::desc("Function name"), cl::NotHidden);
class FunctionInstCounter : public FunctionPass
{
public:
static char ID;
FunctionInstCounter()
: FunctionPass(ID)
{
initializeFunctionInstCounterPass(*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function& func) override
{
if (func.getName() != functionName)
{
return false;
}
unsigned int instCount = 0;
for (BasicBlock& bb : func)
{
instCount += std::distance(bb.begin(), bb.end());
}
llvm::outs() << "Number of instructions in " << func.getName() << ": "
<< instCount << "\n";
return false;
}
};
} // namespace
char FunctionInstCounter::ID = 0;
INITIALIZE_PASS(FunctionInstCounter, "funcinstcount",
"Function instruction counter", false, true)
llvm::Pass* llvm::createFunctionInstCounterPass()
{
return new FunctionInstCounter();
}
You would call it like this:
opt -funcinstcount -funcname=NameOfFunctionHere
bool runOnFunction(Function &F) override {
outs() << "No of Instructions : " <<F.getInstructionCount() << "\n";
}
I guess the above snippet is sufficient for finding the no of instructions in a function
Related
I'm doing some C++ and my app accepts subcommands, for example ./my_app test 123.
I'm semi-new to C++ and I can't find anything on the internet so I don't know haha.
For example in python I'd do:
#!/usr/bin/env python3
import sys
def test(num):
print(f"Test {num}")
subcommands = {"test": test}
subcommands[sys.argv[1](sys.argv[2])
any C++ eq to this? if so, should I use it or stick to if-else_if-else?
Have a look at std::map/std::unordered_map, for example:
#include <iostream>
#include <map>
#include <string>
void test(const std::string &value) {
std::cout << "Test " << value << std::endl;
}
using cmdFuncType = void(*)(const std::string &);
const std::map<std::string, cmdFuncType> subcommands = {
{"test": &test}
};
int main(int argc, char* argv[]) {
if (argc != 3) {
std::cerr << "usage: program command value" << std::endl;
return 0;
}
auto iter = subcommands.find(argv[1]);
if (iter == subcommands.end()) {
std::cerr << "unknown command: " << argv[1] << std::endl;
return 0;
}
iter->second(argv[2]);
return 0;
}
Is this what you are trying to achieve:
#include <string>
#include <functional>
#include <iostream>
#include <map>
void test(int num) {
std::cout << "Test " << num << "\n";
}
std::map<std::string, std::function<void(int)>> subcommands = {
{"test", test}
};
int main(int argc, char* argv[]) {
subcommands[argv[1]](std::atoi(argv[2]));
}
Let me preface by saying I am very new to coding but enjoy learning. I want to randomly generate a number then follow with 700 if statements that will ask a question according to what number is generated. So from the user pov it will randomly ask questions and then will generate another number after.
I've tried the timing random number generators. I can't seem to get rand operator to work. I just want a super basic generator.
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
string a = "placeholder";
cout << "Welcome to Basic Strategy Practice" << endl;
cout << "You are given two aces and the dealer is showing a four. Hit,
double, or split ? " << endl;
cin >> a;
if (a == "split") {
cout << "Correct!" << endl;
}
else {
cout << "Incorrect" << endl;
}
return 0;
}
Basically, I would encapsulate the above code in an if statement that specifies which number was generated after each question is asked. I would think you would just put the if statement inside a while loop of some sort. Thanks!
I would do something like this:
#include <random>
int RandomBetween(int p_min, int p_max)
{
static default_random_engine generator;
std::uniform_int_distribution<int> distribution(p_min, p_max);
return distribution(generator);
}
After that, you can call this function in a switch:
switch(RandomBetween(a, b))
{
...
}
If you want an example of a complete quiz program I made this:
#include <string>
#include <iostream>
#include <tuple>
#include <chrono>
#include <vector>
#include <algorithm>
#include <random>
std::string ToLower(std::string p_target)
{
std::transform(p_target.begin(), p_target.end(), p_target.begin(), [](unsigned char c) { return std::tolower(c); });
return p_target;
}
int RandomBetween(int p_min, int p_max)
{
static std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(p_min, p_max);
return distribution(generator);
}
class Question
{
public:
Question(const std::string& p_message, const std::string& p_answer, bool p_caseSensitive) :
m_message(p_message),
m_answer(p_answer),
m_caseSensitive(p_caseSensitive)
{}
std::tuple<bool, float> Ask() const
{
std::string answer;
std::cout << m_message << std::endl;
std::chrono::time_point<std::chrono::system_clock> start, end;
start = std::chrono::system_clock::now();
std::cin >> answer;
end = std::chrono::system_clock::now();
return { answer == m_answer || (!m_caseSensitive && ToLower(answer) == ToLower(m_answer)), std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() / 1000.0f };
}
private:
std::string m_message;
std::string m_answer;
bool m_caseSensitive;
};
int main()
{
bool gameRunning = true;
std::vector<Question> questions;
questions.emplace_back("Capital of France?", "Paris", false);
questions.emplace_back("Is C++ object oriented? [Y/n]", "y", false);
while (gameRunning)
{
const auto& [success, time] = questions[RandomBetween(0, 1)].Ask();
std::string answerSpeed = "(Answered in: " + std::to_string(time) + "s)";
if (success)
{
std::cout << "You are right!" << answerSpeed << std::endl;
}
else
{
std::cout << "You failed... Game is over!" << answerSpeed << std::endl;
gameRunning = false;
}
}
return 0;
}
Which can (Because it is a random game) outputs:
Capital of France?
Paris
You are right!(Answered in: 1.705000s)
Capital of France?
Paris
You are right!(Answered in: 2.368000s)
Capital of France?
Paris
You are right!(Answered in: 1.657000s)
Is C++ object oriented? [Y/n]
y
You are right!(Answered in: 3.927000s)
Capital of France?
I don't know
You failed... Game is over!(Answered in: 12.921000s)
i search for a way to call a method by its string name.
#include <iostream>
#include <string>
class myClass{
public:
void method1(int run){
std::cout << run << std::endl;
}
void method2(int run){
std::cout << run << std::endl;
}
};
int main(){
myClass mc;
std::string call;
call = "method1";
mc.call(1);
call = "method2";
mc.call(2);
}
But the result, is
‘class Myclass’ has no member named ‘call’
I need response "1" and "2";
EDIT :: Very thank's for your help, i get the next solution (i don't know is good for all cases );
#include <iostream>
#include <string>
class myClass{
public:
void method1(int run){
std::cout << "Loaded method => " << run << std::endl;
}
void method2(int run){
std::cout << "Loaded method => " << run << std::endl;
}
void _loadMethods(int method, int params){
switch(method) {
case 1:
method1(params);
break;
case 2:
method2(params);
break;
default:
break;
}
}
};
int main(){
myClass mc;
std::string method;
method = "method2";
if(method == "method1"){
mc._loadMethods(1, 1);
}
if(method == "method2"){
mc._loadMethods(2, 2);
}
}
Thank's
This is not possible in "raw" C++. But... What you are trying to achieve is some kind of Reflection or Class meta-type information.
You can look at this project: http://www.axelmenzel.de/projects/coding/rttr , use Qt: http://doc.qt.io/qt-5/qmetatype.html#details or google for C++ reflection.
In following code, I think that structure stSameNameButDifferent is local scope definition and so no problem for it. But I got error in run-time.
(error : process crash)
Can you explain what's wrong with that code?
test_function.h
#ifndef TEST_FUNC_H_
#define TEST_FUNC_H_
void test_a();
void test_b();
#endif
main.cpp
#include <iostream>
#include "test_function.h"
using namespace std;
int main(int argc, const char** argv)
{
cout << "testing for struct scope" << endl;
test_a();
test_b();
return 0;
}
test_a.cpp
#include <iostream>
#include <sstream>
#include <cstdint>
#include <list>
#include "test_function.h"
struct stSameNameButDifferent
{
uint32_t nPlayCode;
uint32_t nGameID;
std::string sGameName;
};
void test_a()
{
std::list<stSameNameButDifferent> lstSt;
for(int i=0; i<10; ++i)
{
stSameNameButDifferent st;
st.nPlayCode = i;
st.nGameID = 100+i;
std::ostringstream osBuf;
osBuf << "Game_" << i;
st.sGameName = osBuf.str();
lstSt.push_back(st);
}
for(auto &st : lstSt)
{
std::cout << st.nPlayCode << ", " << st.nGameID << ", " << st.sGameName << std::endl;
}
}
test_b.cpp
#include <iostream>
#include <sstream>
#include <cstdint>
#include <list>
#include "test_function.h"
struct stSameNameButDifferent
{
uint32_t nPlayCode;
uint32_t nGameID;
float fDiscountRate;
std::string sGameName;
};
void test_b()
{
std::list<stSameNameButDifferent> lstSt;
for(int i=0; i<10; ++i)
{
stSameNameButDifferent st;
st.nPlayCode = i;
st.nGameID = 1000+i;
st.fDiscountRate = (float)i/100;
std::ostringstream osBuf;
osBuf << "Game_" << i;
st.sGameName = osBuf.str();
lstSt.push_back(st);
}
for(auto &st : lstSt)
{
std::cout << st.nPlayCode << ", " << st.nGameID << ", " << st.sGameName << std::endl;
}
}
To avoid clashes of the same struct names in multiple translation units, you have to put them in an unnamed namespace like so:
namespace {
struct stSameNameButDifferent {
uint32_t nPlayCode;
uint32_t nGameID;
std::string sGameName;
};
}
This will make stSameNameButDifferent only seen privately in the corresponding translation unit (.cpp file).
Otherwise the linker will resolve the symbol with the first one found, hence the errors you see at runtime.
you have defined stSameNameButDifferent in global scope, so compiler cannot see and analyze both definitions to same struct and it only take the first one it meet and that's why you are getting an error.
You can use two different namespaces for test_a and test_b, so you will not get any error.
I am compiling my program which uses Clang 3.5 on Ubuntu 13.04 x86 machine. I wanted to get all the variables declared in a cpp project. Here is what I wrote:-
// Declares clang::SyntaxOnlyAction.
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
// Declares llvm::cl::extrahelp.
#include "llvm/Support/CommandLine.h"
#include "clang/AST/DeclCXX.h"
#include <iostream>
#include <vector>
using namespace clang::tooling;
using namespace llvm;
using namespace clang::ast_matchers;
using namespace clang;
using namespace std;
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
static cl::extrahelp MoreHelp("\nMore help text...");
static cl::OptionCategory MyToolCategory("My Tool Category");
internal::Matcher<Decl> fields = fieldDecl().bind("field");
internal::Matcher<Decl> params = parmVarDecl().bind("param");
internal::Matcher<Decl> vars = varDecl().bind("var");
class VarDeclPrinter : public MatchFinder::MatchCallback {
public:
int counter;
virtual void run(const MatchFinder::MatchResult &Result) {
const Decl* dec;
if(const FieldDecl* field = Result.Nodes.getNodeAs<FieldDecl>("field"))
llvm::outs() << "Member Variable: " << field->getName() << "\t\t"
<< field->getParent()->getQualifiedNameAsString() << "\n";
if(const ParmVarDecl* param = Result.Nodes.getNodeAs<ParmVarDecl>("param"))
llvm::outs() << "Argument Variable: " << param->getName() << "\t\t"
<< ((CXXMethodDecl*)(param->getParentFunctionOrMethod()))->getQualifiedNameAsString() << "\n";
if(const VarDecl* var = Result.Nodes.getNodeAs<VarDecl>("var"))
llvm::outs() << "Local Variable: " << var->getName() << "\t\t"
<< ((CXXMethodDecl*)(var->getParentFunctionOrMethod()))->getQualifiedNameAsString() << "\n";
counter++;
//llvm::outs() << "Variable count: " << counter << "\n";
//ASTContext* Context = Result.Context;
}
};
int main(int argc, const char **argv) {
CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());
VarDeclPrinter VarDeclCallback;
MatchFinder Finder;
Finder.addMatcher(fields, &VarDeclCallback);
Finder.addMatcher(params, &VarDeclCallback);
Finder.addMatcher(vars, &VarDeclCallback);
return Tool.run(newFrontendActionFactory(&Finder));
}
When I try running this program, I get segmentation fault (possibly when I am casting var->getParentFunctionOrMethod() to CXXMethodDecl*). I wanted the method name where this variable is declared if it is a local variable. Can anybody tell me what may be the reasons for the error? Or what could be a better way to get method name of the variable?
I got the solution. It was because I was trying to fetch method name even if var is not inside method. Here is the solution:-
if(const VarDecl* var = Result.Nodes.getNodeAs<VarDecl>("var")) {
llvm::outs() << "Local Variable: " << var->getName() << "\t\t";
if(var->isFunctionOrMethodVarDecl())
llvm::outs() << ((CXXMethodDecl*)(var->getParentFunctionOrMethod()))->getQualifiedNameAsString();
llvm::outs() << "\n";
}