Hello everyone!
I’ve been working on a code to generate LLVM IR module from C, CXX and CC files in code. I’ve used Clang’s Compiler Instance class and EmitLLVMAction class for the job. However, the code doesn’t work for files that include headers. I had to explicitly mention the include paths, which I thought should’ve been done by the Clang API. Is there a better way to approach this?
Tool.cpp:
int main(int argc, char* argv[]) {
// Prepare compilation arguments
vector<const char *> arg;
arg.push_back(argv[1]);
// Explicitly Add Include Paths
arg.push_back("-I/usr/include");
arg.push_back("-I/usr/local/include");
arg.push_back("-I/usr/lib/llvm-12/lib/clang/12.0.1/include");
arg.push_back("-I/usr/include/x86_64-linux-gnu");
arg.push_back("-I/usr/include");
llvm::ArrayRef<const char *> args(arg);
InitializeAllTargetMCs();
InitializeAllAsmPrinters();
// Prepare DiagnosticEngine
DiagnosticOptions DiagOpts;
TextDiagnosticPrinter *textDiagPrinter = new clang::TextDiagnosticPrinter(errs(), &DiagOpts);
IntrusiveRefCntPtr<clang::DiagnosticIDs> pDiagIDs;
DiagnosticsEngine *pDiagnosticsEngine = new DiagnosticsEngine(pDiagIDs, &DiagOpts, textDiagPrinter);
// Initialize CompilerInvocation
std::shared_ptr<CompilerInvocation> CI = std::make_shared<CompilerInvocation>();
auto compiler = CompilerInvocation::CreateFromArgs(*CI, args, *pDiagnosticsEngine);
if (!compiler) {
errs() << "Error: Could not create compiler invocation.\n";
return 1;
}
// Map code filename to a memoryBuffer
ErrorOr<std::unique_ptr<MemoryBuffer>> FileBufOrErr = MemoryBuffer::getFile(argv[1]);
if (!FileBufOrErr) {
errs() << "Error: Could not open input file " << argv[1] << "\n";
return 1;
}
std::unique_ptr<MemoryBuffer> buffer = std::move(FileBufOrErr.get());
CI->getPreprocessorOpts().addRemappedFile(argv[1], buffer.get());
// Create and initialize CompilerInstance
CompilerInstance Clang;
Clang.setInvocation(CI);
Clang.createDiagnostics();
InitializeAllTargets();
// Create and execute action
CodeGenAction *compilerAction = new EmitLLVMAction();
bool executeAction = Clang.ExecuteAction(*compilerAction);
if (!executeAction) {
errs() << "Error: Could not execute action.\n";
return 1;
}
std::unique_ptr<llvm::Module> module = compilerAction->takeModule();
if(!module)
{
errs() << "Error: module is null\n";
return 1;
}
}
On another note, it seems to execute correctly but there’s some error with freeing memory.
Error:
a.out: /usr/lib/llvm-12/include/llvm/ADT/IntrusiveRefCntPtr.h:82: llvm::RefCountedBase<clang::DiagnosticOptions>::~RefCountedBase() [Derived = clang::DiagnosticOptions]: Assertion `RefCount == 0 && "Destruction occured when there are still references to this."' failed.
Aborted (core dumped)
Any suggestions for the same would be appreciated.