我尝试使用LLVM / Clang API将源代码编译为LLVM IR。
clang_ir.cpp:
#include <iostream>
#include <clang/Driver/Compilation.h>
#include <clang/Driver/Driver.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <llvm/Support/Host.h>
#include <llvm/Support/Program.h>
#include <llvm/Support/raw_ostream.h>
using namespace std;
using namespace clang;
using namespace clang::driver;
int main(int argc, char** argv)
{
cout << "Starting ----" << std::endl;
// [clang -S -emit-llvm ./test/hello_world.cpp]
// Arguments to pass to the clang driver:
string clangPath = "clang";
string inputPath = "./test/hello_world.cpp";
string outputPath = "hello_world.ll";
vector<const char *> args;
args.push_back(clangPath.c_str());
args.push_back("-S");
args.push_back("-emit-llvm");
args.push_back(inputPath.c_str());
// The clang driver needs a DiagnosticsEngine so it can report problems
clang::DiagnosticOptions *Options = new clang::DiagnosticOptions();
//clang::TextDiagnosticPrinter *DiagClient = new clang::TextDiagnosticPrinter(llvm::errs(), Options);
clang::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new clang::DiagnosticIDs());
clang::DiagnosticsEngine Diags(DiagID, Options);
cout << "making driver" << endl;
// Create the clang driver
clang::driver::Driver TheDriver(args[0], llvm::sys::getDefaultTargetTriple(), outputPath, Diags);
// C++ code
//TheDriver.CCCIsCXX = true;
cout << "making compilation" << endl;
// Create the set of actions to perform
clang::OwningPtr<clang::driver::Compilation> Compilation(TheDriver.BuildCompilation(args));
cout << "printing actions:" << endl;
// Print the set of actions
TheDriver.PrintActions(*Compilation);
std::cout << "Done ----" << std::endl;
// Carry out the actions
int Res = 0;
SmallVector<std::pair<int, const Command *>, 4> FailingCommands;
if (Compilation)
Res = TheDriver.ExecuteCompilation(*Compilation, FailingCommands);
// Report problems
/*
if (Res < 0)
TheDriver.generateCompilationDiagnostics(*Compilation, FailingCommands);
*/
for (SmallVectorImpl< std::pair<int,
const Command *> >::iterator it = FailingCommands.begin(),
ie = FailingCommands.end(); it != ie; ++it) {
int CommandRes = it->first;
const Command *FailingCommand = it->second;
if (!Res)
Res = CommandRes;
// If result status is < 0, then the driver command signalled an error.
// If result status is 70, then the driver command reported a fatal error.
// In these cases, generate additional diagnostic information if possible.
if (CommandRes < 0 || CommandRes == 70) {
TheDriver.generateCompilationDiagnostics(*Compilation, FailingCommand);
break;
}
}
return Res;
}
使用命令行成功构建:
MBA-Anton:构建asmirnov $ clang ++
llvm-config --cxxflags
llvm-config --ldflags
llvm-config --libs all
-lclang -lclangAST -lclangASTMatchers -lclangAnalysis -lclangApplyReplacements -lclangBasic -lclangCodeGen -lclangDriver -lclangDynamicASTMatchers -lclangEdit -lclangFormat -lclangFrontend -lclangFrontendTool -lclangIndex -lclangLex -lclangParse -lclangQuery -lclangRewriteCore -lclangRewriteFrontend -lclangSema -lclangSerialization -lclangStaticAnalyzerCheckers -lclangStaticAnalyzerCore -lclangStaticAnalyzerFrontend -lclangTidy -lclangTidyLLVMModule -lclangTooling ../clang_ir.cpp -o clang_ir MBA-Anton:建立asmirnov $
在运行时遇到断言错误:
MBA-Anton:build asmirnov$ ./clang_ir
Starting ----
making driver
making compilation
Assertion failed: (getClient() && "DiagnosticClient not set!"), function EmitCurrentDiagnostic, file /Users/asmirnov/Documents/dev/src/llvm_34/tools/clang/lib/Basic/Diagnostic.cpp, line 391.
Abort trap: 6
MBA-Anton:build asmirnov$
可能是什么原因?
答案 0 :(得分:1)
很清楚地告诉你问题是什么。 DiagnosticClient
未设置。 DiagnosticEngine
需要DiagnosticClient
- 基本上是一个回调来说明诊断发生时该怎么做。
坦率地说,Clang C ++ API充满了像这样烦人的狗屎。要求他们只是在引擎构造函数中引用一个客户端的引用或指针,这太过分了。你只需要习惯于修复每个断言的失败。