下面这个完整代码
它相对较短,因为它建立在LLVM 流程的基础设施上
后者替我们完成大部分工作
我们从程序使用cl命名空间中的llvm工具(cl代表命令行)来实现我们的命令行接口
需要调用ParseCommandLineOption函数声明cl::类型的全局变量
以显示我们的程序收单个参数,并且该函数是包含位码文件名的string类型
之后我们实例化一个LLVMContext对象,以存放于LLVM编译相关的所有数据
从而使LLVM是线程安全的
MemoryBuffer类位内存块定义的一个只读接口
ParseBitcodeFile函数将使用这个对象来读取我们的输入文件的内容,并解析文件中LLVM IR 的内容
在检查完错误并保证一切正常后,我们遍历该文件中模块的所有函数
LLVM模块的概念类似于翻译单元,其中包含所有编码到位码文件中的内容,也是LLVM层次结构中的最高实体
在它后面的函数
基本都是块
最后是指令
如果只是一个函数声明,则丢弃它,因为我们想要查找函数定义
当我们找到这些函数定义时,将打印它们的名称和它包含的基本块的数量
如果编译此程序,并使用help运行,可以查找已经准备好的LLVM命令执行功能
想要找到转换为LLVM IR 的C或C++文件,然后将其转换并使用程序进行分析:
clang -c -emit-llvm xxx.c -o xxx.bc
helloword mysource.bc
遇到个错误,这里的文件头的路径是有问题的
后面我改了一下
然后还是不行
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Module.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/CommandLine.h>
#include <string>
#include<iostream>
suing namesapace llvm;
static cl::opt<std::string>FileName (cl::Positional, c ::desc ("Birtcodefile"),cl::Required);
int main(int argc char**argv)
{
cl::ParseCommandLineOptions(argc,argv,"LLVM hello world\n");
LLVMContext context;
stad::string error;
OwningPtr <MemoryBuffer> mb;
Memorybuffer: :getFile(FileNmae .mb);
Moudle *m=ParseBitcodeFile(mb.get(),context,&error);
if(m==0)
{
std:cerr<<"Errorreading bitcode:"<<error<<std::end:
return -1;
}
raw os ostream o(std::cout);
for (Module::conset iterator = m->getFunctionList().begin(),e=m->getFunctionList.end();i!=e;++i)
{
if (!i->isDeclaration())
{
o<<i->getName()<<"has"<<i-size()<<"basic block(s). \n".;
}
}
return 0
}
后面我才发现,需要clang++,并且我之前的那个makefile文件没有启动的
而且这个文件头问题很大,c++和c和混合
所以换个方法
// 引入相关LLVM头文件
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Module.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/CommandLine.h>
using namespace llvm;
// LLVM上下文全局变量
static ManagedStatic<LLVMContext> GlobalContext;
// 命令行位置参数全局变量, 这个参数的含义是需要处理的LLVM IR字节码的文件名
static cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<filename>.bc"), cl::Required);
int main(int argc, char **argv) {
// 诊断实例
SMDiagnostic Err;
// 格式化命令行参数,
cl::ParseCommandLineOptions(argc, argv);
// 读取并格式化LLVM IR字节码文件, 返回LLVM Module(Module是LLVM IR的顶级容器)
std::unique_ptr<Module> M = parseIRFile(InputFilename, Err, *GlobalContext);
// 错误处理
if (!M) {
Err.print(argv[0], errs());
return 1;
}
// 遍历Module中的每一个Function
for (Function &F:*M) {
// 过滤掉那些以llvm.开头的无关函数
if (!F.isIntrinsic()) {
// 打印函数返回类型
outs() << *(F.getReturnType());
// 打印函数名
outs() << ' ' << F.getName() << '(';
// 遍历函数的每一个参数
for (Function::arg_iterator it = F.arg_begin(), ie = F.arg_end(); it != ie; it++) {
// 打印参数类型
outs() << *(it->getType());
if (it != ie - 1) {
outs() << ", ";
}
}
outs() << ")\n";
}
}
}
这里我测试了之前我写的文章中那个sum函数https://blog.csdn.net/m0_72827793/article/details/135894096